diff --git a/build.gradle b/build.gradle index 42a502e..fe37c50 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'java' group "mod.sin" -version "1.0" +version "1.1" repositories { mavenCentral() @@ -12,8 +12,9 @@ repositories { dependencies { compile 'org.gotti.wurmunlimited:server-modlauncher:0.37' - compile 'com.github.Sindusk:sindusklibrary:v1.5' + compile 'com.github.Sindusk:sindusklibrary:v1.7' compile 'com.github.Sindusk:DiscordRelay:v1.2' + compile 'com.github.Sindusk:DUSKombat:v1.0' compile 'com.github.Sindusk:TreasureHunting:1.1.4' } diff --git a/src/main/java/com/wurmonline/server/questions/AffinityOrbQuestion.java b/src/main/java/com/wurmonline/server/questions/AffinityOrbQuestion.java index c198cd7..9af6961 100644 --- a/src/main/java/com/wurmonline/server/questions/AffinityOrbQuestion.java +++ b/src/main/java/com/wurmonline/server/questions/AffinityOrbQuestion.java @@ -22,7 +22,7 @@ public AffinityOrbQuestion(Creature aResponder, String aTitle, String aQuestion, this.affinityOrb = orb; } - public static HashMap affinityMap = new HashMap<>(); + public HashMap affinityMap = new HashMap<>(); @Override public void answer(Properties answer) { diff --git a/src/main/java/com/wurmonline/server/questions/LeaderboardCustomQuestion.java b/src/main/java/com/wurmonline/server/questions/LeaderboardCustomQuestion.java index f67e688..123e9a1 100644 --- a/src/main/java/com/wurmonline/server/questions/LeaderboardCustomQuestion.java +++ b/src/main/java/com/wurmonline/server/questions/LeaderboardCustomQuestion.java @@ -296,6 +296,33 @@ protected void topPlayerStats(String statName, int limit){ throw new RuntimeException(e); } } + protected void mostCitizens(int limit){ + Connection dbcon; + PreparedStatement ps; + ResultSet rs; + String name; + int skillNum; + String mayor; + double stat; + try { + dbcon = DbConnector.getZonesDbCon(); + ps = dbcon.prepareStatement("SELECT name, maxcitizens, mayor FROM villages WHERE disbanded = 0 ORDER BY maxcitizens DESC LIMIT "+limit); + rs = ps.executeQuery(); + while(rs.next()){ + name = rs.getString(1); + stat = rs.getInt(2); + mayor = rs.getString(3); + stat++; // Add one citizen to account for mayor. + names.add(name); + values.add(stat); + extra.add(mayor); + } + DbUtilities.closeDatabaseObjects(ps, rs); + } + catch (SQLException e) { + throw new RuntimeException(e); + } + } @Override public void sendQuestion() { @@ -347,24 +374,29 @@ public void sendQuestion() { ignoreOpt = true; break; case 8: + limit = 100; + mostCitizens(limit); + ignoreOpt = true; + break; + case 9: limit = 10; topPlayerStats("kills", limit); ignoreOpt = true; break; - case 9: + case 10: limit = 10; topPlayerStats("deaths", limit); ignoreOpt = true; break; - case 10: + case 11: limit = 10; topPlayerStats("depots", limit); ignoreOpt = true; break; } - f.addBoldText("Top "+limit+" players in "+this.getQuestion(), new String[0]); - f.addText("\n\n", new String[0]); + f.addBoldText("Top "+limit+" players in "+this.getQuestion()); + f.addText("\n\n"); int i = 0; DecimalFormat df = new DecimalFormat(".000"); if(!format){ @@ -392,11 +424,11 @@ public void sendQuestion() { } i++; } - f.addText(" \n", new String[0]); + f.addText(" \n"); f.beginHorizontalFlow(); f.addButton("Ok", "okay"); f.endHorizontalFlow(); - f.addText(" \n", new String[0]); + f.addText(" \n"); this.getResponder().getCommunicator().sendBml(400, 500, true, true, f.toString(), 150, 150, 200, this.title); } } diff --git a/src/main/java/com/wurmonline/server/questions/LeaderboardQuestion.java b/src/main/java/com/wurmonline/server/questions/LeaderboardQuestion.java index cbb6301..759463e 100644 --- a/src/main/java/com/wurmonline/server/questions/LeaderboardQuestion.java +++ b/src/main/java/com/wurmonline/server/questions/LeaderboardQuestion.java @@ -144,13 +144,15 @@ public String getCustomOptions(){ customMap.put(6, "Most Unique Achievements"); builder = builder + ",Largest Structures"; customMap.put(7, "Largest Structures"); + builder = builder + ",Most Populated Villages"; + customMap.put(8, "Most Populated Villages"); if(Servers.localServer.PVPSERVER || this.getResponder().getPower() >= 5){ builder = builder + ",PvP Kills"; - customMap.put(8, "PvP Kills"); + customMap.put(9, "PvP Kills"); builder = builder + ",PvP Deaths"; - customMap.put(9, "PvP Deaths"); + customMap.put(10, "PvP Deaths"); builder = builder + ",Depots Captured"; - customMap.put(10, "PvP Depots Captured"); + customMap.put(11, "PvP Depots Captured"); } return builder; } diff --git a/src/main/java/com/wurmonline/server/questions/LeaderboardSkillQuestion.java b/src/main/java/com/wurmonline/server/questions/LeaderboardSkillQuestion.java index 91c5815..5c168bd 100644 --- a/src/main/java/com/wurmonline/server/questions/LeaderboardSkillQuestion.java +++ b/src/main/java/com/wurmonline/server/questions/LeaderboardSkillQuestion.java @@ -4,8 +4,6 @@ import com.wurmonline.server.creatures.Creature; import com.wurmonline.server.deities.Deities; import com.wurmonline.server.skills.SkillList; -import com.wurmonline.server.skills.SkillSystem; -import com.wurmonline.server.skills.SkillTemplate; import com.wurmonline.server.utils.DbUtilities; import net.coldie.tools.BmlForm; import org.gotti.wurmunlimited.modsupport.ModSupportDb; @@ -36,6 +34,29 @@ public void answer(Properties answer) { } } + public int[] getSkilLevelColors(double skill){ + int[] colors = new int[3]; + colors[0] = 0; // No red value + if(skill >= 90){ + double percentTowards100 = 1-((100-skill)*0.1); // Division by 10 + double greenPower = 128 + (128*percentTowards100); + colors[1] = (int) Math.min(255, greenPower); + colors[2] = (int) Math.max(0, 255-greenPower); + }else if(skill >= 50){ + double percentTowards90 = 1-((90-skill)*0.025); // Division by 40 + double greenPower = percentTowards90*128; + colors[1] = (int) Math.max(128, greenPower); + colors[2] = (int) Math.min(255, 255-greenPower); + }else{ + double percentTowards50 = 1-((50-skill)*0.02); // Division by 50 + double otherPower = 255 - (percentTowards50*255); + colors[0] = (int) Math.min(255, otherPower); + colors[1] = (int) Math.min(255, Math.max(128, otherPower)); + colors[2] = 255; + } + return colors; + } + protected HashMap optIn = new HashMap<>(); protected void identifyOptIn(){ String name; @@ -95,8 +116,8 @@ public void sendQuestion() { catch (SQLException e) { throw new RuntimeException(e); } - f.addBoldText("Top 20 players in "+this.getQuestion(), new String[0]); - f.addText("\n\n", new String[0]); + f.addBoldText("Top 20 players in "+this.getQuestion()); + f.addText("\n\n"); int i = 0; DecimalFormat df = new DecimalFormat(".000"); while(i < names.size() && i < skills.size()){ @@ -109,19 +130,20 @@ public void sendQuestion() { if(skillNum == SkillList.CHANNELING){ extra = " ("+ Deities.getDeityName(deities.get(i))+")"; } + int[] color = getSkilLevelColors(skills.get(i)); if(names.get(i).equals(this.getResponder().getName())){ name = names.get(i); - f.addBoldText(df.format(skills.get(i)) + " - " + name + extra); + f.addBoldColoredText(df.format(skills.get(i)) + " - " + name + extra, color[0], color[1], color[2]); }else{ - f.addText(df.format(skills.get(i)) + " - " + name + extra); + f.addColoredText(df.format(skills.get(i)) + " - " + name + extra, color[0], color[1], color[2]); } i++; } - f.addText(" \n", new String[0]); + f.addText(" \n"); f.beginHorizontalFlow(); f.addButton("Ok", "okay"); f.endHorizontalFlow(); - f.addText(" \n", new String[0]); + f.addText(" \n"); this.getResponder().getCommunicator().sendBml(400, 500, true, true, f.toString(), 150, 150, 200, this.title); } } diff --git a/src/main/java/mod/sin/actions/LeaderboardSkillAction.java b/src/main/java/mod/sin/actions/LeaderboardSkillAction.java new file mode 100644 index 0000000..ad8e971 --- /dev/null +++ b/src/main/java/mod/sin/actions/LeaderboardSkillAction.java @@ -0,0 +1,101 @@ +package mod.sin.actions; + +import com.wurmonline.server.behaviours.Action; +import com.wurmonline.server.behaviours.ActionEntry; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.players.Player; +import com.wurmonline.server.questions.LeaderboardSkillQuestion; +import com.wurmonline.server.skills.NoSuchSkillException; +import com.wurmonline.server.skills.Skill; +import org.gotti.wurmunlimited.modsupport.actions.ActionPerformer; +import org.gotti.wurmunlimited.modsupport.actions.BehaviourProvider; +import org.gotti.wurmunlimited.modsupport.actions.ModAction; +import org.gotti.wurmunlimited.modsupport.actions.ModActions; + +import java.util.Collections; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class LeaderboardSkillAction implements ModAction { + private static Logger logger = Logger.getLogger(LeaderboardSkillAction.class.getName()); + + private final short actionId; + private final ActionEntry actionEntry; + + public LeaderboardSkillAction() { + logger.log(Level.WARNING, "LeaderboardSkillAction()"); + + actionId = (short) ModActions.getNextActionId(); + actionEntry = ActionEntry.createEntry( + actionId, + "Open leaderboard", + "opening", + new int[] { 0 /* ACTION_TYPE_NOMOVE */ } // 6 /* ACTION_TYPE_NOMOVE */, 48 /* ACTION_TYPE_ENEMY_ALWAYS */, 36 /* ACTION_TYPE_ALWAYS_USE_ACTIVE_ITEM */ + ); + ModActions.registerAction(actionEntry); + } + + @Override + public BehaviourProvider getBehaviourProvider() + { + return new BehaviourProvider() { + @Override + public List getBehavioursFor(Creature performer, Skill skill) { + if(performer instanceof Player && skill.getNumber() > 0) { + return Collections.singletonList(actionEntry); + } + + return null; + } + + // Never called + @Override + public List getBehavioursFor(Creature performer, Item source, Skill skill) { + if (performer instanceof Player && skill.getNumber() > 0) { + return Collections.singletonList(actionEntry); + } + + return null; + } + }; + } + + @Override + public ActionPerformer getActionPerformer() + { + return new ActionPerformer() { + + @Override + public short getActionId() { + return actionId; + } + @Override + public boolean action(Action act, Creature performer, Skill skill, short action, float counter) { + LeaderboardSkillQuestion lbsq = new LeaderboardSkillQuestion(performer, "Leaderboard", skill.getName(), performer.getWurmId(), skill.getNumber()); + lbsq.sendQuestion(); + return true; + } + + // Without activated object + @Override + public boolean action(Action act, Creature performer, Item source, Skill skill, short action, float counter) { + if(performer instanceof Player){ + this.action(act, performer, skill, action, counter); + }else{ + logger.info("Somehow a non-player opened a leaderboard..."); + } + return true; + } + + @Override + public boolean action(Action act, Creature performer, Item source, Item target, short action, float counter) + { + return this.action(act, performer, target, action, counter); + } + + + }; // ActionPerformer + } +} \ No newline at end of file diff --git a/src/main/java/mod/sin/actions/items/AffinityCatcherCaptureAction.java b/src/main/java/mod/sin/actions/items/AffinityCatcherCaptureAction.java index d9b4e15..1ebbc53 100644 --- a/src/main/java/mod/sin/actions/items/AffinityCatcherCaptureAction.java +++ b/src/main/java/mod/sin/actions/items/AffinityCatcherCaptureAction.java @@ -40,14 +40,14 @@ public AffinityCatcherCaptureAction() { } public static boolean hasAffinityCatcher(Creature performer){ - logger.info("Checking if creature has affinity catcher."); + //logger.info("Checking if creature has affinity catcher."); for(Item i : performer.getInventory().getItems()){ if(i.getTemplateId() == AffinityCatcher.templateId){ - logger.info("Has affinity catcher."); + //logger.info("Has affinity catcher."); return true; } } - logger.info("No affinity catcher found."); + //logger.info("No affinity catcher found."); return false; } @@ -94,7 +94,6 @@ public boolean action(Action act, Creature performer, Skill skill, short action, // Without activated object @Override public boolean action(Action act, Creature performer, Item source, Skill skill, short action, float counter) { - logger.info("Action with item."); if(performer instanceof Player){ Player player = (Player) performer; if (source.getTemplate().getTemplateId() != AffinityCatcher.templateId){ @@ -134,7 +133,7 @@ public boolean action(Action act, Creature performer, Item source, Skill skill, // Only called if the affinity is not found or it breaks from having less than one. player.getCommunicator().sendNormalServerMessage("You must have an affinity in the skill to capture."); }else{ - logger.info("Somehow a non-player activated an Affinity Orb..."); + logger.info("Somehow a non-player activated an Affinity Catcher..."); } return true; } diff --git a/src/main/java/mod/sin/actions/items/AffinityCatcherConsumeAction.java b/src/main/java/mod/sin/actions/items/AffinityCatcherConsumeAction.java index 6ccf050..e4b01bf 100644 --- a/src/main/java/mod/sin/actions/items/AffinityCatcherConsumeAction.java +++ b/src/main/java/mod/sin/actions/items/AffinityCatcherConsumeAction.java @@ -98,9 +98,15 @@ public boolean action(Action act, Creature performer, Item target, short action, return true; } Affinities.setAffinity(player.getWurmId(), skillNum, affinity.getNumber() + 1, false); + player.getCommunicator().sendSafeServerMessage("Your affinity grows stronger."); Items.destroyItem(target.getWurmId()); return true; } + // Has no affinity in this, so should give them one. + Affinities.setAffinity(player.getWurmId(), skillNum, 1, false); + player.getCommunicator().sendSafeServerMessage("You obtain a new affinity."); + Items.destroyItem(target.getWurmId()); + return true; }else{ logger.info("Somehow a non-player activated an Affinity Orb..."); } diff --git a/src/main/java/mod/sin/actions/items/KeyCombinationAction.java b/src/main/java/mod/sin/actions/items/KeyCombinationAction.java new file mode 100644 index 0000000..db59b4e --- /dev/null +++ b/src/main/java/mod/sin/actions/items/KeyCombinationAction.java @@ -0,0 +1,388 @@ +package mod.sin.actions.items; + +import com.wurmonline.server.Items; +import com.wurmonline.server.Server; +import com.wurmonline.server.behaviours.Action; +import com.wurmonline.server.behaviours.ActionEntry; +import com.wurmonline.server.creatures.Communicator; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.deities.Deities; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.items.ItemFactory; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.players.Player; +import mod.sin.items.KeyFragment; +import mod.sin.wyvern.KeyEvent; +import mod.sin.wyvern.MiscChanges; +import org.gotti.wurmunlimited.modsupport.actions.ActionPerformer; +import org.gotti.wurmunlimited.modsupport.actions.BehaviourProvider; +import org.gotti.wurmunlimited.modsupport.actions.ModAction; +import org.gotti.wurmunlimited.modsupport.actions.ModActions; +import org.nyxcode.wurm.discordrelay.DiscordRelay; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class KeyCombinationAction implements ModAction { + private static Logger logger = Logger.getLogger(KeyCombinationAction.class.getName()); + + private final short actionId; + private final ActionEntry actionEntry; + + public KeyCombinationAction() { + logger.log(Level.WARNING, "KeyCombinationAction()"); + + actionId = (short) ModActions.getNextActionId(); + actionEntry = ActionEntry.createEntry( + actionId, + "Call upon the heavens", + "intervening", + new int[] { 6 /* ACTION_TYPE_NOMOVE */ } // 6 /* ACTION_TYPE_NOMOVE */, 48 /* ACTION_TYPE_ENEMY_ALWAYS */, 36 /* ACTION_TYPE_ALWAYS_USE_ACTIVE_ITEM */ + ); + ModActions.registerAction(actionEntry); + } + + + @Override + public BehaviourProvider getBehaviourProvider() + { + return new BehaviourProvider() { + // Menu with activated object + @Override + public List getBehavioursFor(Creature performer, Item source, Item object) + { + return this.getBehavioursFor(performer, object); + } + + // Menu without activated object + @Override + public List getBehavioursFor(Creature performer, Item object) + { + if(performer instanceof Player && object != null && object.getTemplateId() == KeyFragment.templateId) { + return Collections.singletonList(actionEntry); + } + + return null; + } + }; + } + + @Override + public ActionPerformer getActionPerformer() + { + return new ActionPerformer() { + + @Override + public short getActionId() { + return actionId; + } + + protected boolean hasEnoughFragments(Creature performer){ + int count = 0; + for(Item item : performer.getInventory().getItems()){ + if(item.getTemplateId() == KeyFragment.templateId){ + count++; + } + } + return count >= 50; + } + protected void removeFragments(Creature performer){ + int count = 0; + int index = 0; + ArrayList fragments = new ArrayList<>(); + for(Item item : performer.getInventory().getItems()){ + if(item.getTemplateId() == KeyFragment.templateId && count < 50){ + fragments.add(item.getWurmId()); + count++; + } + } + for(long wid : fragments){ + Items.destroyItem(wid); + } + } + + protected void broadcast(Creature performer, int speaker, String message){ + String name; + int r; + int g; + int b; + if(speaker == 0){ + name = "Unknown Entity"; + r = 0; + g = 255; + b = 255; + }else if(speaker == Deities.DEITY_FO){ + name = "Fo"; + r = 128; + g = 255; + b = 128; + }else if(speaker == Deities.DEITY_MAGRANON){ + name = "Magranon"; + r = 255; + g = 128; + b = 128; + }else if(speaker == Deities.DEITY_VYNORA){ + name = "Vynora"; + r = 192; + g = 192; + b = 255; + }else if(speaker == Deities.DEITY_LIBILA){ + name = "Libila"; + r = 192; + g = 192; + b = 192; + }else{ + name = Deities.getEntityName(speaker); + r = 192; + g = 192; + b = 192; + } + MiscChanges.sendGlobalFreedomChat(performer, name, message, r, g, b); + DiscordRelay.sendToDiscord("gl-freedom", "<"+name+"> "+message, false); + } + + // Without activated object + @Override + public boolean action(Action act, Creature performer, Item target, short action, float counter) + { + try{ + if(performer instanceof Player){ + if(target.getTemplateId() != KeyFragment.templateId){ + performer.getCommunicator().sendNormalServerMessage("That is not a key fragment."); + return true; + } + if(target.getLastOwnerId() != performer.getWurmId() && target.getOwnerId() != performer.getWurmId()){ + performer.getCommunicator().sendNormalServerMessage("You must own the "+target.getName()+" to begin."); + return true; + } + Communicator comm = performer.getCommunicator(); + if(counter == 1.0f){ + if(!hasEnoughFragments(performer)){ + performer.getCommunicator().sendSafeServerMessage("You must obtain enough fragments to form a full key before you begin."); + return true; + } + performer.getCommunicator().sendNormalServerMessage("You begin to combine the the key fragments."); + Server.getInstance().broadCastAction(performer.getName() + " begins unseal "+performer.getHisHerItsString()+" "+target.getName()+".", performer, 5); + act.setTimeLeft(3800); + performer.sendActionControl("Heaven intervention", true, act.getTimeLeft()); + KeyEvent.setActive(System.currentTimeMillis(), performer); + }else if(act.currentSecond() == 5){ + comm.sendAlertServerMessage("Stand still and do not move until the process is complete.", (byte) 2); + }else if(act.currentSecond() == 9){ + comm.sendAlertServerMessage("Pay attention to GL-Freedom chat, and respond to divine inquiries there.", (byte) 2); + }else if(act.currentSecond() == 13){ + comm.sendAlertServerMessage("Answer the inquiries directly in GL-Freedom.", (byte) 2); + }else if(act.currentSecond() == 17){ + comm.sendAlertServerMessage("You have 20 to 30 seconds to answer each question. Let's begin.", (byte) 2); + }else if(act.currentSecond() == 20){ + broadcast(performer, 0, "What is this I feel? Something is happening."); + }else if(act.currentSecond() == 25){ + broadcast(performer, 0, "Who is this creature? This... "+performer.getName()+"..."); + }else if(act.currentSecond() == 29){ + broadcast(performer, 0, "Ah, there you are. Like a speck of dust. I see you."); + }else if(act.currentSecond() == 33){ + broadcast(performer, 0, "You possess a large quantity of divine power."); + }else if(act.currentSecond() == 37){ + broadcast(performer, 0, "I'll take it. In exchange, I will grant you one wish."); + }else if(act.currentSecond() == 40){ + broadcast(performer, 0, "Let's hear it. "+performer.getName()+": What do you desire most? Power? Wealth? Recognition?"); + }else if(act.currentSecond() == 50){ // Reminder + if(KeyEvent.getResponse(0).equals("")) { + broadcast(performer, 0, "Nothing to say? I'll give you a few more seconds..."); + } + }else if(act.currentSecond() == 60){ + String response = KeyEvent.getResponse(0); + if(response.equals("")){ + broadcast(performer, 0, "No answer. Just as I expected."); + }else { + broadcast(performer, 0, "Hah! You want " + KeyEvent.getResponse(0) + "? Such a lack of imagination."); + } + }else if(act.currentSecond() == 65){ + if(performer.getDeity() != null) { + broadcast(performer, performer.getDeity().getNumber(), "Master, I recognize this one."); + }else{ + broadcast(performer, 1+Server.rand.nextInt(4), "This one seems important."); // Random entity. + } + }else if(act.currentSecond() == 70){ + if(performer.getDeity() != null){ + broadcast(performer, performer.getDeity().getNumber(), performer.getName()+" is my champion, and possesses the fragments of the hunt."); + }else{ + broadcast(performer, 1+Server.rand.nextInt(4), "They possess the fragments of the hunt."); + } + }else if(act.currentSecond() == 75){ + if(performer.getDeity() != null){ + broadcast(performer, 0, "Silence, "+performer.getDeity().getName()+"! I was just offering a trade, that's all."); + }else{ + broadcast(performer, 0, "Silence! I was just offering a trade, that's all."); + } + }else if(act.currentSecond() == 80){ + if(performer.getDeity() != null){ + broadcast(performer, performer.getDeity().getNumber(), "Master, you know the rules. Ascension is required."); + }else{ + broadcast(performer, 1+Server.rand.nextInt(4), "Master, you know the rules. Ascension is required."); + } + }else if(act.currentSecond() == 84){ + broadcast(performer, 0, "Yes, yes. Rules and tradition and all that wonderful stuff. Alright. Let's begin."); + }else if(act.currentSecond() == 88){ + broadcast(performer, 0, performer.getName()+"! Your efforts have not gone unnoticed."); + }else if(act.currentSecond() == 92){ + broadcast(performer, 0, "For your valor, I shall lift you into the heavens and bestow upon you ascension to demigod."); + }else if(act.currentSecond() == 95){ + broadcast(performer, 0, "A shame, really. Now you wont get "+KeyEvent.getResponse(0)+". Oh well."); + }else if(act.currentSecond() == 99){ + broadcast(performer, 1+Server.rand.nextInt(4), "Master..."); + }else if(act.currentSecond() == 103){ + broadcast(performer, 0, "I digress. We, as the council of the heavens, shall grant you one power each."); + }else if(act.currentSecond() == 107){ + broadcast(performer, 0, "Fo. We'll start with you."); + }else if(act.currentSecond() == 110){ + broadcast(performer, Deities.DEITY_FO, "Greetings, "+performer.getName()+". I am Fo, the Silence and the Trees."); + }else if(act.currentSecond() == 114){ + broadcast(performer, Deities.DEITY_FO, "For you, I grant a decision between four of my powers."); + }else if(act.currentSecond() == 117){ + broadcast(performer, Deities.DEITY_FO, KeyEvent.getFoPowers()); + }else if(act.currentSecond() == 120){ + broadcast(performer, Deities.DEITY_FO, "Choose, "+performer.getName()+": Which power do you select?"); + }else if(act.currentSecond() == 140){ + if(KeyEvent.getResponse(1).equals("")){ + broadcast(performer, Deities.DEITY_FO, "Are you still there? "+performer.getName()+", you must choose."); + } + }else if(act.currentSecond() == 150){ + if(!KeyEvent.isValidFo()) { + broadcast(performer, Deities.DEITY_FO, "If you refuse to choose, I will choose for you. I grant you Life Transfer."); + KeyEvent.foPower = "Life Transfer"; + KeyEvent.hasWeaponEnchant = true; + }else{ + broadcast(performer, Deities.DEITY_FO, "I hear you, "+performer.getName()+", and grant you the power of "+KeyEvent.foPower+"."); + } + }else if(act.currentSecond() == 155){ + broadcast(performer, 0, "Your first power is "+KeyEvent.foPower+" from Fo. Next up, Magranon."); + }else if(act.currentSecond() == 159){ + broadcast(performer, Deities.DEITY_MAGRANON, "Greetings, "+performer.getName()+". I am Magranon, the Fire and the Mountain."); + }else if(act.currentSecond() == 163){ + broadcast(performer, Deities.DEITY_MAGRANON, "I was going to offer you six powers, but you already chose "+KeyEvent.foPower+", which is incompatible with one of mine."); + }else if(act.currentSecond() == 167){ + broadcast(performer, Deities.DEITY_MAGRANON, KeyEvent.getMagranonPowers()); + }else if(act.currentSecond() == 170){ + broadcast(performer, Deities.DEITY_MAGRANON, "Choose, "+performer.getName()+": Which power do you wish to wield?"); + }else if(act.currentSecond() == 190){ + if (KeyEvent.getResponse(2).equals("")) { + broadcast(performer, Deities.DEITY_MAGRANON, "Are you still there? " + performer.getName() + ", you must choose."); + } + }else if(act.currentSecond() == 200){ + if (!KeyEvent.isValidMagranon()) { + KeyEvent.setRandomMagranonPower(); + broadcast(performer, Deities.DEITY_MAGRANON, "If you refuse to choose, I will choose for you. I grant you "+KeyEvent.magranonPower+"."); + } else { + broadcast(performer, Deities.DEITY_MAGRANON, "I hear you, " + performer.getName() + ", and grant you the power of " + KeyEvent.magranonPower + "."); + } + }else if(act.currentSecond() == 205){ + broadcast(performer, 0, "Your second power is "+KeyEvent.magranonPower+" from Magranon. Your next power shall come from Vynora."); + }else if(act.currentSecond() == 209){ + broadcast(performer, Deities.DEITY_VYNORA, "Greetings, "+performer.getName()+". I am Vynora, the Water and the Wind."); + }else if(act.currentSecond() == 213){ + broadcast(performer, Deities.DEITY_VYNORA, "I have much to offer you. Unlike my peers, I can only offer you enchant powers to choose from."); + }else if(act.currentSecond() == 217){ + broadcast(performer, Deities.DEITY_VYNORA, KeyEvent.getVynoraPowers()); + }else if(act.currentSecond() == 220){ + broadcast(performer, Deities.DEITY_VYNORA, "Choose, "+performer.getName()+": Which enchant power suits your needs?"); + }else if(act.currentSecond() == 240){ + if (KeyEvent.getResponse(3).equals("")) { + broadcast(performer, Deities.DEITY_VYNORA, "Are you still there? " + performer.getName() + ", you must choose."); + } + }else if(act.currentSecond() == 250) { + if (!KeyEvent.isValidVynora()) { + KeyEvent.setRandomVynoraPower(); + broadcast(performer, Deities.DEITY_VYNORA, "If you refuse to choose, I will choose for you. I grant you " + KeyEvent.vynoraPower + "."); + } else { + broadcast(performer, Deities.DEITY_VYNORA, "I hear you, " + performer.getName() + ", and grant you the power of " + KeyEvent.vynoraPower + "."); + } + }else if(act.currentSecond() == 255){ + broadcast(performer, 0, "Your third power is "+KeyEvent.vynoraPower+" from Vynora. You have one more to choose. Libila!"); + }else if(act.currentSecond() == 259){ + broadcast(performer, Deities.DEITY_LIBILA, "Greetings, "+performer.getName()+". I am Libila, the Hate and the Deceit."); + }else if(act.currentSecond() == 263){ + broadcast(performer, Deities.DEITY_LIBILA, "My offerings are the most powerful of all, so choose wisely."); + }else if(act.currentSecond() == 267){ + broadcast(performer, Deities.DEITY_LIBILA, KeyEvent.getLibilaPowers()); + }else if(act.currentSecond() == 270){ + broadcast(performer, Deities.DEITY_LIBILA, "Choose, "+performer.getName()+": What shall be your strongest power?"); + }else if(act.currentSecond() == 290){ + if (KeyEvent.getResponse(4).equals("")) { + broadcast(performer, Deities.DEITY_LIBILA, "Are you still there? " + performer.getName() + ", you must choose."); + } + }else if(act.currentSecond() == 300) { + if (!KeyEvent.isValidLibila()) { + KeyEvent.setRandomLibilaPower(); + broadcast(performer, Deities.DEITY_LIBILA, "If you refuse to choose, I will choose for you. I grant you " + KeyEvent.libilaPower + "."); + } else { + broadcast(performer, Deities.DEITY_LIBILA, "I hear you, " + performer.getName() + ", and grant you the power of " + KeyEvent.libilaPower + "."); + } + }else if(act.currentSecond() == 305){ + broadcast(performer, 0, "So it appears you have completed your choices."); + }else if(act.currentSecond() == 310){ + broadcast(performer, 0, "Upon ascension, you will receive "+KeyEvent.foPower+", "+KeyEvent.magranonPower+", "+KeyEvent.vynoraPower+", and "+KeyEvent.libilaPower); + }else if(act.currentSecond() == 314){ + broadcast(performer, 0, "There is one last question to answer. Which of the council shall you base your ascension on?"); + }else if(act.currentSecond() == 318){ + broadcast(performer, 0, "Each comes with their own benefit. They will explain them to you."); + }else if(act.currentSecond() == 322){ + broadcast(performer, Deities.DEITY_FO, "I can grant you immunity to thorns and the wildlife shall no longer be aggressive."); + }else if(act.currentSecond() == 326){ + broadcast(performer, Deities.DEITY_MAGRANON, "I can grant you immunity to lava and increased learning from combat."); + }else if(act.currentSecond() == 330){ + broadcast(performer, Deities.DEITY_VYNORA, "I can grant you industrial aptitude."); + }else if(act.currentSecond() == 334){ + broadcast(performer, Deities.DEITY_LIBILA, "I can grant you healing and replenishment from mycelium."); + }else if(act.currentSecond() == 340){ + broadcast(performer, 0, "The choice is yours, "+performer.getName()+": Which deity shall you base your ascension on? Fo, Magranon, Vynora, or Libila?"); + }else if(act.currentSecond() == 360){ + if (KeyEvent.getResponse(5).equals("")) { + broadcast(performer, 0, "Are you still there? " + performer.getName() + ", you must choose."); + } + }else if(act.currentSecond() == 370) { + if (!KeyEvent.isValidAscendTemplate()) { + KeyEvent.setRandomAscendTemplate(); + broadcast(performer, 0, "If you refuse to choose, I will choose for you. Your ascension shall be based on " + KeyEvent.ascendTemplate + "."); + } else { + broadcast(performer, 0, "Your ascension shall be based on " + KeyEvent.ascendTemplate + "."); + } + }else if(act.currentSecond() == 375){ + broadcast(performer, 0, "With this council concluded, I now award you, "+performer.getName()+", with the Key of the Heavens."); + }else if(act.currentSecond() == 378){ + broadcast(performer, 0, "Use it, and claim your place among the gods."); + }else if(counter * 10f > performer.getCurrentAction().getTimeLeft()){ + if(!hasEnoughFragments(performer)){ + performer.getCommunicator().sendSafeServerMessage("You have lost the fragments required."); + return true; + } + removeFragments(performer); + Item key = ItemFactory.createItem(ItemList.keyHeavens, 99.0f, "Entity"); + performer.getInventory().insertItem(key, true); + performer.getCommunicator().sendSafeServerMessage("You obtain a "+key.getTemplate().getName()+"!"); + logger.info("Player "+performer.getName()+" obtained "+key.getName()+" - "+KeyEvent.foPower+", "+KeyEvent.magranonPower+", "+KeyEvent.vynoraPower+", "+KeyEvent.libilaPower+", "+KeyEvent.ascendTemplate); + return true; + } + }else{ + logger.info("Somehow a non-player activated a Treasure Box..."); + } + return false; + }catch(Exception e){ + e.printStackTrace(); + return true; + } + } + + @Override + public boolean action(Action act, Creature performer, Item source, Item target, short action, float counter) + { + return this.action(act, performer, target, action, counter); + } + + + }; // ActionPerformer + } +} \ No newline at end of file diff --git a/src/main/java/mod/sin/actions/items/SealedMapAction.java b/src/main/java/mod/sin/actions/items/SealedMapAction.java index cbbb422..25909a6 100644 --- a/src/main/java/mod/sin/actions/items/SealedMapAction.java +++ b/src/main/java/mod/sin/actions/items/SealedMapAction.java @@ -6,6 +6,7 @@ import java.util.logging.Level; import java.util.logging.Logger; +import mod.sin.items.KeyFragment; import org.gotti.wurmunlimited.modsupport.actions.ActionPerformer; import org.gotti.wurmunlimited.modsupport.actions.BehaviourProvider; import org.gotti.wurmunlimited.modsupport.actions.ModAction; @@ -75,7 +76,7 @@ public ActionPerformer getActionPerformer() public short getActionId() { return actionId; } - + // Without activated object @Override public boolean action(Action act, Creature performer, Item target, short action, float counter) @@ -92,7 +93,7 @@ public boolean action(Action act, Creature performer, Item target, short action, } if(counter == 1.0f){ performer.getCommunicator().sendNormalServerMessage("You begin to unseal the "+target.getName()+"."); - Server.getInstance().broadCastAction(performer.getName() + " begins unseal "+performer.getHisHerItsString()+" "+target.getName()+".", performer, 5); + Server.getInstance().broadCastAction(performer.getName() + " begins unsealing "+performer.getHisHerItsString()+" "+target.getName()+".", performer, 5); act.setTimeLeft(50); performer.sendActionControl("Unsealing", true, act.getTimeLeft()); }else if(counter * 10f > performer.getCurrentAction().getTimeLeft()){ diff --git a/src/main/java/mod/sin/creatures/Facebreyker.java b/src/main/java/mod/sin/creatures/Facebreyker.java index b5a4b18..dc1631c 100644 --- a/src/main/java/mod/sin/creatures/Facebreyker.java +++ b/src/main/java/mod/sin/creatures/Facebreyker.java @@ -57,6 +57,8 @@ public CreatureTemplateBuilder createCreateTemplateBuilder() { builder.baseCombatRating(80.0f); builder.combatDamageType(Wound.TYPE_CRUSH); builder.maxGroupAttackSize(100); + + builder.setCombatMoves(new int[]{5}); //builder.usesNewAttacks(true); // float baseDamage, float criticalChance, float baseSpeed, int attackReach, int weightGroup, byte damageType, boolean usesWeapon, int rounds, float waitUntilNextAttack diff --git a/src/main/java/mod/sin/creatures/SpiritTroll.java b/src/main/java/mod/sin/creatures/SpiritTroll.java index 331102c..a0c4941 100644 --- a/src/main/java/mod/sin/creatures/SpiritTroll.java +++ b/src/main/java/mod/sin/creatures/SpiritTroll.java @@ -57,7 +57,7 @@ public CreatureTemplateBuilder createCreateTemplateBuilder() { // final float naturalArmour, final float handDam, final float kickDam, final float biteDam, final float headDam, final float breathDam, final float speed, final int moveRate, // final int[] itemsButchered, final int maxHuntDist, final int aggress) { CreatureTemplateBuilder builder = new CreatureTemplateBuilder("mod.creature.spirit.troll", "Spirit troll", "A spirit troll.", - "model.creature.humanoid.troll.standard", Servers.localServer.PVPSERVER ? pvpTypes : types, BodyTemplate.TYPE_HUMAN, (short) 5, (byte) 0, (short) 85, (short) 50, (short) 85, + "model.creature.humanoid.troll.king", Servers.localServer.PVPSERVER ? pvpTypes : types, BodyTemplate.TYPE_HUMAN, (short) 5, (byte) 0, (short) 85, (short) 50, (short) 85, "sound.death.troll", "sound.death.troll", "sound.combat.hit.troll", "sound.combat.hit.troll", 0.15f, 15f, 17f, 19.0f, 0.0f, 0.0f, 1.2f, 500, new int[]{}, 10, 74, Materials.MATERIAL_MEAT_HUMANOID); diff --git a/src/main/java/mod/sin/items/StatuetteBreyk.java b/src/main/java/mod/sin/items/StatuetteBreyk.java index 8f8614b..ade8265 100644 --- a/src/main/java/mod/sin/items/StatuetteBreyk.java +++ b/src/main/java/mod/sin/items/StatuetteBreyk.java @@ -17,10 +17,10 @@ public class StatuetteBreyk implements ItemTypes, MiscConstants { public static Logger logger = Logger.getLogger(StatuetteBreyk.class.getName()); public static int templateId; - private String name = "statuette of Breyk"; + private String name = "statuette of Thelastdab"; public void createTemplate() throws IOException{ ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.statuette.breyk"); - itemBuilder.name(name, "statuettes", "A statuette resembling the artists interpretation of the deity Breyk."); + itemBuilder.name(name, "statuettes", "A statuette resembling the artists interpretation of the demigod Thelastdab."); itemBuilder.itemTypes(new short[]{ // {108, 52, 22, 44, 87, 92, 147} - Statuette ItemTypes.ITEM_TYPE_NAMED, ItemTypes.ITEM_TYPE_DECORATION, @@ -37,7 +37,7 @@ public void createTemplate() throws IOException{ itemBuilder.dimensions(3, 5, 20); itemBuilder.primarySkill(-10); itemBuilder.bodySpaces(MiscConstants.EMPTY_BYTE_PRIMITIVE_ARRAY); - itemBuilder.modelName("model.decoration.statuette.fo."); + itemBuilder.modelName("model.decoration.statuette.magranon."); itemBuilder.difficulty(40.0f); itemBuilder.weightGrams(1000); itemBuilder.material(Materials.MATERIAL_SILVER); diff --git a/src/main/java/mod/sin/items/TitaniumLump.java b/src/main/java/mod/sin/items/TitaniumLump.java new file mode 100644 index 0000000..e59f8bf --- /dev/null +++ b/src/main/java/mod/sin/items/TitaniumLump.java @@ -0,0 +1,52 @@ +package mod.sin.items; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.*; +import com.wurmonline.server.skills.SkillList; +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import java.io.IOException; +import java.util.logging.Logger; + +public class TitaniumLump { + private static Logger logger = Logger.getLogger(TitaniumLump.class.getName()); + public static int templateId; + private String name = "lump, titanium"; + public void createTemplate() throws IOException{ + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.lump.titanium"); + itemBuilder.name(name, "titanium lumps", "A lightweight lump of glistening titanium."); + itemBuilder.itemTypes(new short[]{ // {22, 146, 46, 113, 157} - Addy Lump + ItemTypes.ITEM_TYPE_METAL, + ItemTypes.ITEM_TYPE_BULK, + ItemTypes.ITEM_TYPE_COMBINE + }); + itemBuilder.imageNumber((short) 638); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(3, 3, 3); + itemBuilder.primarySkill(-10); + itemBuilder.bodySpaces(MiscConstants.EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.resource.lump."); + itemBuilder.difficulty(40.0f); + itemBuilder.weightGrams(400); + itemBuilder.material(Materials.MATERIAL_UNDEFINED); + itemBuilder.value(200); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } + + public void initCreationEntry(){ + logger.info("initCreationEntry()"); + if(templateId > 0){ + logger.info("Creating "+name+" creation entry, ID = "+templateId); + // CreationEntryCreator.createSimpleEntry(10041, 220, 47, 223, true, true, 0.0f, false, false, CreationCategories.RESOURCES); + CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_METALLURGY, ItemList.adamantineBar, ItemList.glimmerSteelBar, + templateId, true, true, 0.0f, true, false, CreationCategories.RESOURCES); + }else{ + logger.info(name+" does not have a template ID on creation entry."); + } + } +} diff --git a/src/main/java/mod/sin/items/TitaniumSocket.java b/src/main/java/mod/sin/items/TitaniumSocket.java new file mode 100644 index 0000000..82d816e --- /dev/null +++ b/src/main/java/mod/sin/items/TitaniumSocket.java @@ -0,0 +1,50 @@ +package mod.sin.items; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.*; +import com.wurmonline.server.skills.SkillList; +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import java.io.IOException; +import java.util.logging.Logger; + +public class TitaniumSocket { + private static Logger logger = Logger.getLogger(TitaniumSocket.class.getName()); + public static int templateId; + private String name = "titanium socket"; + public void createTemplate() throws IOException{ + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.socket.titanium"); + itemBuilder.name(name, "titanium sockets", "A socket for a gem, designed for insertion into an item."); + itemBuilder.itemTypes(new short[]{ // {22, 146, 46, 113, 157} - Addy Lump + ItemTypes.ITEM_TYPE_METAL + }); + itemBuilder.imageNumber((short) 250); // Bracelet + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(3, 3, 3); + itemBuilder.primarySkill(-10); + itemBuilder.bodySpaces(MiscConstants.EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.resource.lump."); + itemBuilder.difficulty(40.0f); + itemBuilder.weightGrams(1000); + itemBuilder.material(Materials.MATERIAL_UNDEFINED); + itemBuilder.value(200); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } + + public void initCreationEntry(){ + logger.info("initCreationEntry()"); + if(templateId > 0){ + logger.info("Creating "+name+" creation entry, ID = "+templateId); + // CreationEntryCreator.createSimpleEntry(10041, 220, 47, 223, true, true, 0.0f, false, false, CreationCategories.RESOURCES); + CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_GOLDSMITHING, ItemList.anvilSmall, TitaniumLump.templateId, + templateId, false, true, 0.0f, true, false, CreationCategories.JEWELRY); + }else{ + logger.info(name+" does not have a template ID on creation entry."); + } + } +} diff --git a/src/main/java/mod/sin/wyvern/AntiCheat.java b/src/main/java/mod/sin/wyvern/AntiCheat.java index 4b89ab1..a1fbd3d 100644 --- a/src/main/java/mod/sin/wyvern/AntiCheat.java +++ b/src/main/java/mod/sin/wyvern/AntiCheat.java @@ -44,11 +44,16 @@ public static void mapPlayerSteamId(String name, String steamId){ boolean foundSteamIdMap = false; try { dbcon = ModSupportDb.getModSupportDb(); - ps = dbcon.prepareStatement("SELECT * FROM SteamIdMap"); + ps = dbcon.prepareStatement("SELECT * FROM SteamIdMap WHERE NAME=? AND STEAMID=?"); + ps.setString(1, name); + ps.setString(2, steamId); ResultSet rs = ps.executeQuery(); while (rs.next()) { - if (!rs.getString("NAME").equals(name)) continue; - foundSteamIdMap = true; + if(!foundSteamIdMap) { + foundSteamIdMap = true; + }else{ + logger.warning(String.format("Player %s has accessed their account from multiple Steam ID's!", name)); + } } rs.close(); ps.close(); @@ -59,7 +64,9 @@ public static void mapPlayerSteamId(String name, String steamId){ logger.info("No steam id entry for " + name + ". Creating one."); try { dbcon = ModSupportDb.getModSupportDb(); - ps = dbcon.prepareStatement("INSERT INTO SteamIdMap (NAME, STEAMID) VALUES(\"" + name + "\", " + steamId + ")"); + ps = dbcon.prepareStatement("INSERT INTO SteamIdMap (NAME, STEAMID) VALUES(?, ?)"); + ps.setString(1, name); + ps.setString(2, steamId); ps.executeUpdate(); ps.close(); } catch (SQLException e) { diff --git a/src/main/java/mod/sin/wyvern/Arena.java b/src/main/java/mod/sin/wyvern/Arena.java index a83f02d..d04f88c 100644 --- a/src/main/java/mod/sin/wyvern/Arena.java +++ b/src/main/java/mod/sin/wyvern/Arena.java @@ -230,6 +230,7 @@ public static void preInit(){ + " $_ = $proceed($$);" + "}"; Util.instrumentDeclared(thisClass, ctCommunicator, "reallyHandle_CMD_MOVE_INVENTORY", "getDominator", replace); + Util.instrumentDeclared(thisClass, ctCommunicator, "equipCreatureCheck", "getDominator", replace); /*ctCommunicator.getDeclaredMethod("reallyHandle_CMD_MOVE_INVENTORY").instrument(new ExprEditor(){ public void edit(MethodCall m) throws CannotCompileException { if (m.getMethodName().equals("getDominator")) { @@ -784,16 +785,16 @@ public void edit(MethodCall m) throws CannotCompileException { Util.instrumentDeclaredCount(thisClass, ctCreature, "die", "isOnCurrentServer", 1, replace); Util.setReason("Disable player skill loss on Arena."); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER && this.isPlayer() && this.isDeathProtected()){" + - " this.getCommunicator().sendSafeServerMessage(\"You have died on the Arena server with a Resurrection Stone and your knowledge is kept safe.\");" + + replace = "if(this.isPlayer() && this.isDeathProtected()){" + + " this.getCommunicator().sendSafeServerMessage(\"You have died with a Resurrection Stone and your knowledge is kept safe.\");" + " return;" + - "}else if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + - " this.getCommunicator().sendAlertServerMessage(\"You have died on the Arena server without a Resurrection Stone, resulting in some of your knowledge being lost.\");" + + "}else{" + + " this.getCommunicator().sendAlertServerMessage(\"You have died without a Resurrection Stone, resulting in some of your knowledge being lost.\");" + "}"; Util.insertBeforeDeclared(thisClass, ctCreature, "punishSkills", replace); Util.setReason("Disable player fight skill loss on Arena."); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER && this.isPlayer() && this.isDeathProtected()){" + + replace = "if(this.isPlayer() && this.isDeathProtected()){" + " $_ = null;" + "}else{" + " $_ = $proceed($$);" + @@ -809,6 +810,14 @@ public void edit(MethodCall m) throws CannotCompileException { "}"; Util.instrumentDeclared(thisClass, ctPlayer, "modifyRanking", "getAffinities", replace); + /*Util.setReason("Enable stealing from deeds."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " $_ = true;" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctMethodsItems, "checkIfStealing", "mayPass", replace);*/ + }catch (NotFoundException e) { throw new HookException(e); diff --git a/src/main/java/mod/sin/wyvern/Bounty.java b/src/main/java/mod/sin/wyvern/Bounty.java index e7727b1..bd7b25f 100644 --- a/src/main/java/mod/sin/wyvern/Bounty.java +++ b/src/main/java/mod/sin/wyvern/Bounty.java @@ -26,25 +26,6 @@ public class Bounty { //protected static WyvernMods mod; public static HashMap reward = new HashMap<>(); - // Using a hook in CombatEngine.addWound, we call this function to create a list of creatures that actually inflicted damage. - public static HashMap> dealtDamage = new HashMap<>(); - public static void addDealtDamage(long defender, long attacker, double damage){ - if(dealtDamage.containsKey(defender)){ - Map 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 dealers = new HashMap<>(); - dealers.put(attacker, damage); - dealtDamage.put(defender, dealers); - } - } - public static long lastAttacked(Map attackers, long playerId){ return System.currentTimeMillis()-attackers.get(playerId); } @@ -219,7 +200,7 @@ public void edit(MethodCall m) throws CannotCompileException { + "}");*/ // -- When a creature takes damage, track the damage taken -- // - CtClass[] params2 = { + /*CtClass[] params2 = { ctCreature, ctCreature, CtClass.byteType, @@ -235,11 +216,10 @@ public void edit(MethodCall m) throws CannotCompileException { }; String desc2 = Descriptor.ofMethod(CtClass.booleanType, params2); CtClass ctCombatEngine = classPool.get("com.wurmonline.server.combat.CombatEngine"); - replace = "" - + "if($1 != null && $2 != null){" + replace = "if($1 != null && $2 != null){" + " "+Bounty.class.getName()+".addDealtDamage($2.getWurmId(), $1.getWurmId(), $5);" + "}"; - Util.insertBeforeDescribed(thisClass, ctCombatEngine, "addWound", desc2, replace); + 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);}"); } diff --git a/src/main/java/mod/sin/wyvern/DatabaseHelper.java b/src/main/java/mod/sin/wyvern/DatabaseHelper.java index a6c0d83..13ee335 100644 --- a/src/main/java/mod/sin/wyvern/DatabaseHelper.java +++ b/src/main/java/mod/sin/wyvern/DatabaseHelper.java @@ -34,7 +34,8 @@ public static void onPlayerLogin(Player p){ logger.info("No leaderboard entry for "+p.getName()+". Creating one."); try { dbcon = ModSupportDb.getModSupportDb(); - ps = dbcon.prepareStatement("INSERT INTO LeaderboardOpt (name) VALUES(\"" + p.getName() + "\")"); + ps = dbcon.prepareStatement("INSERT INTO LeaderboardOpt (name) VALUES(?)"); + ps.setString(1, p.getName()); ps.executeUpdate(); ps.close(); } diff --git a/src/main/java/mod/sin/wyvern/DeityChanges.java b/src/main/java/mod/sin/wyvern/DeityChanges.java index 5e1a732..620872a 100644 --- a/src/main/java/mod/sin/wyvern/DeityChanges.java +++ b/src/main/java/mod/sin/wyvern/DeityChanges.java @@ -1,23 +1,29 @@ package mod.sin.wyvern; +import com.wurmonline.server.deities.Deities; +import com.wurmonline.server.deities.Deity; + import java.util.logging.Logger; public class DeityChanges { public static Logger logger = Logger.getLogger(DeityChanges.class.getName()); public static void onServerStarted(){ - /*if(Deities.getDeity(101) != null){ // Edit Breyk player god - Deity breyk = Deities.getDeity(101); + if(Deities.getDeity(101) != null){ // Edit Thelastdab Player God + Deity thelastdab = Deities.getDeity(101); // Add some defining affinities - breyk.repairer = true; - breyk.learner = true; - breyk.deathProtector = true; - breyk.befriendCreature = true; + thelastdab.metalAffinity = true; + thelastdab.deathProtector = true; + thelastdab.mountainGod = true; + thelastdab.warrior = true; // Remove some affinities - breyk.warrior = false; - breyk.healer = false; - breyk.clayAffinity = false; - }*/ + thelastdab.learner = false; + thelastdab.repairer = false; + thelastdab.befriendCreature = false; + thelastdab.healer = false; + thelastdab.clayAffinity = false; + thelastdab.waterGod = false; + } /*if(Deities.getDeity(102) != null){ // Edit Cyberhusky player god Deity cyberhusky = Deities.getDeity(102); // Add some defining affinities diff --git a/src/main/java/mod/sin/wyvern/GemAugmentation.java b/src/main/java/mod/sin/wyvern/GemAugmentation.java new file mode 100644 index 0000000..f6ba55b --- /dev/null +++ b/src/main/java/mod/sin/wyvern/GemAugmentation.java @@ -0,0 +1,50 @@ +package mod.sin.wyvern; + +import com.wurmonline.server.items.Item; +import javassist.ClassPool; +import javassist.CtClass; +import javassist.NotFoundException; +import mod.sin.lib.Util; +import org.gotti.wurmunlimited.modloader.classhooks.HookException; +import org.gotti.wurmunlimited.modloader.classhooks.HookManager; + +import java.util.logging.Logger; + +public class GemAugmentation { + public static Logger logger = Logger.getLogger(GemAugmentation.class.getName()); + + public static boolean setGemmedQuality(Item target, double power, float maxGain, float modifier){ + logger.info(String.format("Item %s [QL %.2f] improved with power %.1f, max gain %.1f, modifier %.1f", + target.getName(), target.getQualityLevel(), power, maxGain, modifier)); + return target.setQualityLevel(Math.min(999.9f, (float)((double)target.getQualityLevel() + power * (double)maxGain * (double) (modifier * target.getMaterialImpBonus())))); + } + + public static void preInit(){ + try { + ClassPool classPool = HookManager.getInstance().getClassPool(); + Class thisClass = GemAugmentation.class; + String replace; + + Util.setReason("Primary Gem Augmentation Hook."); + CtClass ctMethodsItems = classPool.get("com.wurmonline.server.behaviours.MethodsItems"); + replace = "$_ = "+GemAugmentation.class.getName()+".setGemmedQuality($0, power, maxGain, modifier);"; + Util.instrumentDeclared(thisClass, ctMethodsItems, "improveItem", "setQualityLevel", replace); + Util.instrumentDeclared(thisClass, ctMethodsItems, "polishItem", "setQualityLevel", replace); + Util.instrumentDeclared(thisClass, ctMethodsItems, "temper", "setQualityLevel", replace); + + Util.setReason("Prevent action power from being diluted."); + replace = "$_ = $proceed((float)power);"; + Util.instrumentDeclared(thisClass, ctMethodsItems, "improveItem", "setPower", replace); + Util.instrumentDeclared(thisClass, ctMethodsItems, "polishItem", "setPower", replace); + Util.instrumentDeclared(thisClass, ctMethodsItems, "temper", "setPower", replace); + + CtClass ctDbItem = classPool.get("com.wurmonline.server.items.DbItem"); + replace = //"logger.info(\"qlevel = \"+qlevel);" + + "$_ = $proceed(9999.9f, $2);"; + Util.instrumentDeclared(thisClass, ctDbItem, "setQualityLevel", "min", replace); + + }catch (NotFoundException e) { + throw new HookException(e); + } + } +} diff --git a/src/main/java/mod/sin/wyvern/ItemMod.java b/src/main/java/mod/sin/wyvern/ItemMod.java index e6f3716..ce40779 100644 --- a/src/main/java/mod/sin/wyvern/ItemMod.java +++ b/src/main/java/mod/sin/wyvern/ItemMod.java @@ -50,6 +50,7 @@ public class ItemMod { public static CorpseDecoration CORPSE_DECORATION = new CorpseDecoration(); public static DepthDrill DEPTH_DRILL = new DepthDrill(); public static DisintegrationRod DISINTEGRATION_ROD = new DisintegrationRod(); + //public static TitaniumLump ELECTRUM_LUMP = new TitaniumLump(); public static EnchantOrb ENCHANT_ORB = new EnchantOrb(); public static EternalOrb ETERNAL_ORB = new EternalOrb(); public static Eviscerator EVISCERATOR = new Eviscerator(); @@ -115,6 +116,7 @@ public static void createItems(){ CORPSE_DECORATION.createTemplate(); DEPTH_DRILL.createTemplate(); DISINTEGRATION_ROD.createTemplate(); + //ELECTRUM_LUMP.createTemplate(); ENCHANT_ORB.createTemplate(); ETERNAL_ORB.createTemplate(); EVISCERATOR.createTemplate(); @@ -183,6 +185,7 @@ public static void registerActions(){ ModActions.registerAction(new EnchantOrbAction()); ModActions.registerAction(new EternalOrbAction()); ModActions.registerAction(new FriyanTabletAction()); + ModActions.registerAction(new KeyCombinationAction()); ModActions.registerAction(new SealedMapAction()); ModActions.registerAction(new SupplyDepotAction()); ModActions.registerAction(new TreasureBoxAction()); @@ -197,12 +200,13 @@ public static void initCreationEntries(){ //COIN_DECORATION.initCreationEntry(); //CORPSE_DECORATION.initCreationEntry(); DEPTH_DRILL.initCreationEntry(); + //ELECTRUM_LUMP.initCreationEntry(); EVISCERATOR.initCreationEntry(); KNUCKLES.initCreationEntry(); MASS_STORAGE_UNIT.initCreationEntry(); //SKELETON_DECORATION.initCreationEntry(); SOUL_FORGE.initCreationEntry(); - //STATUETTE_BREYK.initCreationEntry(); + STATUETTE_BREYK.initCreationEntry(); //STATUETTE_CYBERHUSKY.initCreationEntry(); WARHAMMER.initCreationEntry(); WARHAMMER_HEAD.initCreationEntry(); @@ -331,19 +335,31 @@ public static void modifyItems() throws NoSuchTemplateException, IllegalArgument ItemTemplate leather = ItemTemplateFactory.getInstance().getTemplate(ItemList.leather); ReflectionUtil.setPrivateField(leather, ReflectionUtil.getField(leather.getClass(), "combine"), true); - // Make logs able to be combined. + // Make logs able to be combined. Also reduce their volume. ItemTemplate log = ItemTemplateFactory.getInstance().getTemplate(ItemList.log); ReflectionUtil.setPrivateField(log, ReflectionUtil.getField(log.getClass(), "combine"), true); ReflectionUtil.setPrivateField(log, ReflectionUtil.getField(log.getClass(), "centimetersZ"), 50); int newVolume = log.getSizeX()*log.getSizeY()*log.getSizeZ(); ReflectionUtil.setPrivateField(log, ReflectionUtil.getField(log.getClass(), "volume"), newVolume); + // Reduce kindling volume as well to make sure they're not larger than logs. + ItemTemplate kindling = ItemTemplateFactory.getInstance().getTemplate(ItemList.kindling); + ReflectionUtil.setPrivateField(kindling, ReflectionUtil.getField(kindling.getClass(), "centimetersY"), 10); + ReflectionUtil.setPrivateField(kindling, ReflectionUtil.getField(kindling.getClass(), "centimetersZ"), 10); + int newKindlingVolume = kindling.getSizeX()*kindling.getSizeY()*kindling.getSizeZ(); + ReflectionUtil.setPrivateField(kindling, ReflectionUtil.getField(kindling.getClass(), "volume"), newKindlingVolume); + // Set silver mirror price to 10 silver instead of 1 iron. ItemTemplate handMirror = ItemTemplateFactory.getInstance().getTemplate(ItemList.handMirror); ReflectionUtil.setPrivateField(handMirror, ReflectionUtil.getField(handMirror.getClass(), "value"), 200000); ItemTemplate goldMirror = ItemTemplateFactory.getInstance().getTemplate(ItemList.goldenMirror); ReflectionUtil.setPrivateField(goldMirror, ReflectionUtil.getField(goldMirror.getClass(), "value"), 1000000); + // Creature crates to 10 silver. + ItemTemplate creatureCage = ItemTemplateFactory.getInstance().getTemplate(ItemList.creatureCrate); + ReflectionUtil.setPrivateField(creatureCage, ReflectionUtil.getField(creatureCage.getClass(), "value"), 100000); + ReflectionUtil.setPrivateField(creatureCage, ReflectionUtil.getField(creatureCage.getClass(), "fullprice"), true); + // 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); @@ -414,9 +430,15 @@ public static void modifyItems() throws NoSuchTemplateException, IllegalArgument setFragments(AffinityOrb.templateId, 20); + // Tier 4 setFragments(ItemList.statueWorg, 40); setFragments(ItemList.statueEagle, 40); + // Tier 5 + setFragments(ItemList.statueHellHorse, 45); + setFragments(ItemList.statueDrake, 45); + + // Tier 6 setFragments(ItemList.statueFo, 50); setFragments(ItemList.statueMagranon, 50); setFragments(ItemList.statueLibila, 50); diff --git a/src/main/java/mod/sin/wyvern/KeyEvent.java b/src/main/java/mod/sin/wyvern/KeyEvent.java new file mode 100644 index 0000000..3283982 --- /dev/null +++ b/src/main/java/mod/sin/wyvern/KeyEvent.java @@ -0,0 +1,396 @@ +package mod.sin.wyvern; + +import com.wurmonline.server.Message; +import com.wurmonline.server.Server; +import com.wurmonline.server.TimeConstants; +import com.wurmonline.server.creatures.Creature; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.logging.Logger; + +public class KeyEvent { + public static Logger logger = Logger.getLogger(KeyEvent.class.getName()); + + protected static class Response{ + protected int index; + protected long startTime; + protected long endTime; + protected String response = ""; + public Response(int index, int startSecond, int endSecond){ + this.index = index; + this.startTime = startSecond * TimeConstants.SECOND_MILLIS; + this.endTime = endSecond * TimeConstants.SECOND_MILLIS; + } + public void setResponse(String response){ + this.response = response; + } + public String getResponse(){ + return response; + } + } + + protected static ArrayList responses = new ArrayList<>(); + protected static void resetResponses(){ + responses.clear(); + responses.add(new Response(0, 40, 60)); // Desire + responses.add(new Response(1, 120, 150)); // Fo's Power + responses.add(new Response(2, 170, 200)); // Magranon's Power + responses.add(new Response(3, 220, 250)); // Vynora's Power + responses.add(new Response(4, 270, 300)); // Liblia's Power + responses.add(new Response(5, 340, 370)); // Ascend Template + + // Reset booleans + hasWeaponEnchant = false; + hasCreatureEnchant = false; + hasIndustryEnchant = false; + hasHeal = false; + hasTame = false; + } + public static String getResponse(int index){ + for(Response r : responses){ + if(r.index == index){ + return r.getResponse(); + } + } + return ""; + } + + public static boolean hasWeaponEnchant = false; + public static boolean hasCreatureEnchant = false; + public static boolean hasIndustryEnchant = false; + public static boolean hasHeal = false; + public static boolean hasTame = false; + + public static String foPower = ""; + public static String magranonPower = ""; + public static String vynoraPower = ""; + public static String libilaPower = ""; + public static String ascendTemplate = ""; + + public static String getFoPowers(){ + return "I offer the following: Life Transfer, Oakshell, Light of Fo, Charm"; + } + public static boolean isValidFo(){ + return isValidFo(getResponse(1).toLowerCase()); + } + public static boolean isValidFo(String response){ + if(response.contains("life transfer") || response.contains("lifetransfer") || response.equals("lt")){ + foPower = "Life Transfer"; + hasWeaponEnchant = true; + return true; + }else if(response.contains("oakshell") || response.contains("oak shell")){ + foPower = "Oakshell"; + hasCreatureEnchant = true; + return true; + }else if(response.contains("light of fo") || response.contains("lof") || response.contains("light fo")){ + foPower = "Light of Fo"; + hasHeal = true; + return true; + }else if(response.contains("charm") || response.contains("tame")){ + foPower = "Charm"; + hasTame = true; + return true; + } + return false; + } + public static String getMagranonPowers(){ + String builder = "I offer the following: "; + boolean started = false; + if(!hasWeaponEnchant){ + builder += "Flaming Aura"; + started = true; + } + if(!hasCreatureEnchant){ + if(started){ + builder += ", Frantic Charge"; + }else{ + builder += "Frantic Charge"; + started = true; + } + } + if(!hasIndustryEnchant){ + if(started){ + builder += ", Efficiency"; + }else{ + builder += "Efficiency"; + started = true; + } + } + if(!hasHeal){ + if(started){ + builder += ", Mass Stamina"; + }else{ + builder += "Mass Stamina"; + started = true; + } + } + if(!hasTame){ + if(started){ + builder += ", Dominate"; + }else{ + builder += "Dominate"; + } + } + builder += ", Strongwall"; + return builder; + } + public static void setRandomMagranonPower(){ + if(!hasWeaponEnchant){ + magranonPower = "Flaming Aura"; + hasWeaponEnchant = true; + }else if(!hasCreatureEnchant){ + magranonPower = "Frantic Charge"; + hasCreatureEnchant = true; + }else if(!hasIndustryEnchant){ + magranonPower = "Efficiency"; + hasIndustryEnchant = true; + }else{ + magranonPower = "Strongwall"; + } + } + public static boolean isValidMagranon(){ + return isValidMagranon(getResponse(2).toLowerCase()); + } + public static boolean isValidMagranon(String response){ + if((response.contains("flaming aura") || response.contains("flamingaura") || response.contains("flame aura") || response.equals("fa"))){ + magranonPower = "Flaming Aura"; + hasWeaponEnchant = true; + return true; + }else if((response.contains("frantic") || response.contains("charge"))){ + magranonPower = "Frantic Charge"; + hasCreatureEnchant = true; + return true; + }else if((response.contains("mass stam") || response.contains("stamina"))){ + magranonPower = "Mass Stamina"; + hasHeal = true; + return true; + }else if((response.contains("effic") || response.contains("effec"))){ + magranonPower = "Efficiency"; + hasIndustryEnchant = true; + return true; + }else if((response.contains("dominate") || response.contains("dom"))){ + magranonPower = "Dominate"; + hasTame = true; + return true; + }else if(response.contains("wall") || response.contains("strong")){ + magranonPower = "Strongwall"; + return true; + } + return false; + } + public static String getVynoraPowers(){ + String builder = "I offer the following: "; + builder += "Wind of Ages, Circle of Cunning, Aura of Shared Pain"; + if(!hasWeaponEnchant){ + builder += ", Frostbrand, Nimbleness, Mind Stealer"; + } + if(!hasCreatureEnchant){ + builder += ", Excel"; + } + builder += ", Opulence"; + return builder; + } + public static void setRandomVynoraPower(){ + if(!hasWeaponEnchant){ + vynoraPower = "Nimbleness"; + hasWeaponEnchant = true; + }else if(!hasCreatureEnchant){ + vynoraPower = "Excel"; + hasCreatureEnchant = true; + }else{ + vynoraPower = "Wind of Ages"; + hasIndustryEnchant = true; + } + } + public static boolean isValidVynora(){ + return isValidVynora(getResponse(3).toLowerCase()); + } + public static boolean isValidVynora(String response){ + if((response.contains("frost"))){ + vynoraPower = "Frostbrand"; + hasWeaponEnchant = true; + return true; + }else if((response.contains("nimb"))){ + vynoraPower = "Nimbleness"; + hasWeaponEnchant = true; + return true; + }else if((response.contains("mind stealer") || response.contains("mindstealer"))){ + vynoraPower = "Mind Stealer"; + hasWeaponEnchant = true; + return true; + }else if((response.contains("excel"))){ + vynoraPower = "Excel"; + hasCreatureEnchant = true; + return true; + }else if(response.contains("wind") || response.equals("woa")){ + vynoraPower = "Wind of Ages"; + hasIndustryEnchant = true; + return true; + }else if(response.contains("circle") || response.contains("cunning") || response.equals("coc")){ + vynoraPower = "Circle of Cunning"; + hasIndustryEnchant = true; + return true; + }else if(response.contains("aura") || response.contains("shared") || response.equals("aosp")){ + vynoraPower = "Aura of Shared Pain"; + return true; + }else if(response.contains("opulence")){ + vynoraPower = "Opulence"; + return true; + } + return false; + } + public static String getLibilaPowers(){ + String builder = "I offer the following: "; + builder += "Web Armour"; + if(!hasWeaponEnchant){ + builder += ", Bloodthirst, Rotting Touch"; + } + if(!hasCreatureEnchant){ + builder += ", Truehit"; + } + if(!hasHeal){ + builder += ", Scorn of Libila"; + } + if(!hasIndustryEnchant){ + builder += ", Blessings of the Dark"; + } + if(!hasTame){ + builder += ", Rebirth"; + } + builder += ", Drain Health, Drain Stamina"; + return builder; + } + public static void setRandomLibilaPower(){ + if(!hasWeaponEnchant){ + libilaPower = "Rotting Touch"; + hasWeaponEnchant = true; + }else if(!hasCreatureEnchant){ + libilaPower = "Truehit"; + hasCreatureEnchant = true; + }else if(!hasTame){ + libilaPower = "Rebirth"; + hasTame = true; + }else{ + libilaPower = "Drain Health"; + } + } + public static boolean isValidLibila(){ + return isValidLibila(getResponse(4).toLowerCase()); + } + public static boolean isValidLibila(String response){ + if((response.contains("bloodthirst") || response.contains("blood thirst"))){ + libilaPower = "Bloodthirst"; + hasWeaponEnchant = true; + return true; + }else if((response.contains("rotting") || response.contains("touch"))){ + libilaPower = "Rotting Touch"; + hasWeaponEnchant = true; + return true; + }else if((response.contains("truehit") || response.contains("truhit"))){ + libilaPower = "Truehit"; + hasCreatureEnchant = true; + return true; + }else if((response.contains("scorn"))){ + libilaPower = "Scorn of Libila"; + hasHeal = true; + return true; + }else if((response.contains("blessing") || response.contains("dark") || response.equals("botd"))){ + libilaPower = "Blessings of the Dark"; + hasIndustryEnchant = true; + return true; + }else if((response.contains("rebirth"))){ + libilaPower = "Rebirth"; + hasTame = true; + return true; + }else if(response.contains("health")){ + libilaPower = "Drain Health"; + return true; + }else if(response.contains("stam")){ + libilaPower = "Drain Stamina"; + return true; + }else if(response.contains("web") || response.contains("armour")){ + libilaPower = "Web Armour"; + return true; + } + return false; + } + public static void setRandomAscendTemplate(){ + if(Server.rand.nextBoolean()) { + ascendTemplate = "Fo"; + }else{ + ascendTemplate = "Vynora"; + } + } + public static boolean isValidAscendTemplate(){ + return isValidAscendTemplate(getResponse(5).toLowerCase()); + } + public static boolean isValidAscendTemplate(String response){ + if(response.equals("fo")){ + ascendTemplate = "Fo"; + return true; + }else if(response.contains("mag")){ + ascendTemplate = "Magranon"; + return true; + }else if(response.contains("vyn")){ + ascendTemplate = "Vynora"; + return true; + }else if(response.contains("lib")){ + ascendTemplate = "Libila"; + return true; + } + return false; + } + + protected static boolean isValidResponse(int index, String message){ + if (index == 0){ // Desire + return true; + }else if(index == 1){ // Fo Power + return isValidFo(message); + }else if(index == 2){ // Magranon Power + return isValidMagranon(message); + }else if(index == 3) { // Vynora Power + return isValidVynora(message); + }else if(index == 4){ // Libila Power + return isValidLibila(message); + }else if(index == 5){ // Ascend Template + return isValidAscendTemplate(message); + } + return true; + } + + protected static boolean active = false; + protected static long startTime = 0; + protected static Creature performer = null; + public static boolean isActive(){ + return active; + } + + public static void setActive(long time, Creature performer){ + KeyEvent.active = true; + KeyEvent.startTime = time; + KeyEvent.performer = performer; + resetResponses(); + } + + public static void handlePlayerMessage(Message message){ + if(performer == message.getSender()){ + long currentTime = System.currentTimeMillis() - startTime; + //logger.info(String.format("Current timer: %s", currentTime)); + for(Response r : responses){ + //logger.info(String.format("Checking if index %s is valid at time %s (%s to %s)", r.index, currentTime, r.startTime, r.endTime)); + if(r.startTime < currentTime && r.endTime > currentTime){ + String response = message.getMessage().substring(message.getSender().getName().length()+3).toLowerCase(); + //logger.info(String.format("Response at index %s is valid (%s to %s)", r.index, r.startTime, r.endTime)); + if (isValidResponse(r.index, response)) { + r.setResponse(response); + } + } + } + } + } + + public static void preInit(){ + resetResponses(); + } +} diff --git a/src/main/java/mod/sin/wyvern/MiscChanges.java b/src/main/java/mod/sin/wyvern/MiscChanges.java index 85ebd51..798b0c1 100644 --- a/src/main/java/mod/sin/wyvern/MiscChanges.java +++ b/src/main/java/mod/sin/wyvern/MiscChanges.java @@ -3,6 +3,8 @@ import com.wurmonline.server.*; import com.wurmonline.server.bodys.Wound; import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.creatures.Creatures; +import com.wurmonline.server.creatures.NoSuchCreatureException; import com.wurmonline.server.items.Item; import com.wurmonline.server.items.ItemTemplate; import com.wurmonline.server.items.SimpleCreationEntry; @@ -16,6 +18,7 @@ import com.wurmonline.server.zones.VolaTile; import com.wurmonline.server.zones.Zones; import com.wurmonline.shared.constants.Enchants; +import com.wurmonline.shared.util.StringUtilities; import javassist.*; import javassist.bytecode.Descriptor; import javassist.expr.ExprEditor; @@ -31,6 +34,7 @@ import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.HashMap; +import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.logging.Logger; @@ -52,16 +56,19 @@ public void run() { }; r.run(); } - - public static void sendGlobalFreedomChat(final Creature sender, final String message, final int red, final int green, final int blue){ + + public static void sendGlobalFreedomChat(final Creature sender, final String message, final int red, final int green, final int blue){ + sendGlobalFreedomChat(sender, sender.getNameWithoutPrefixes(), message, red, green, blue); + } + public static void sendGlobalFreedomChat(final Creature sender, final String name, final String message, final int red, final int green, final int blue){ Runnable r = () -> { Message mess; for(Player rec : Players.getInstance().getPlayers()){ - mess = new Message(sender, (byte)10, "GL-Freedom", "<"+sender.getNameWithoutPrefixes()+"> "+message, red, green, blue); + mess = new Message(sender, (byte)10, "GL-Freedom", "<"+name+"> "+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); + WcKingdomChat wc = new WcKingdomChat(WurmId.getNextWCCommandId(), sender.getWurmId(), name, message, false, (byte) 4, red, green, blue); if (!Servers.isThisLoginServer()) { wc.sendToLoginServer(); } else { @@ -72,6 +79,29 @@ public static void sendGlobalFreedomChat(final Creature sender, final String mes r.run(); } + public static void broadCastDeathsPvE(Player player, Map attackers){ + StringBuilder attackerString = new StringBuilder(); + final long now = System.currentTimeMillis(); + for (final Long attackerId : attackers.keySet()) { + final Long time = attackers.get(attackerId); + try { + final Creature creature = Creatures.getInstance().getCreature(attackerId); + if (now - time >= 600000L) { + continue; + } + if(attackerString.length() > 0){ + attackerString.append(" "); + } + attackerString.append(StringUtilities.raiseFirstLetter(creature.getName())); + if (creature.isPlayer()) { + return; + } + } + catch (NoSuchCreatureException ignored) {} + } + Players.getInstance().broadCastDeathInfo(player, attackerString.toString()); + } + public static void broadCastDeaths(Creature player, String slayers){ String slayMessage = "slain by "; sendGlobalFreedomChat(player, slayMessage+slayers, 200, 25, 25); @@ -278,8 +308,10 @@ public static void preInit(){ String infoTabTitle = "Server"; // Initial messages: String[] infoTabLine = {"Server Thread: https://forum.wurmonline.com/index.php?/topic/162067-revenant-modded-pvepvp-3x-action-new-skillgain/", - "Website/Maps: https://www.sarcasuals.com/", - "Server Discord: https://discord.gg/r8QNXAC"}; + "Website/Maps: https://www.sarcasuals.com/", + "Server Discord: https://discord.gg/r8QNXAC", + "Server Data: https://docs.google.com/spreadsheets/d/1yjqTHoxUan4LIldI3jgrXZgXj1M2ENQ4MXniPUz0rE4", + "Server Wiki/Documentation: https://docs.google.com/document/d/1GeaygilS-Z-d1TuGB7awOe9sJNV4o5BTZw_a2ATJy98"}; StringBuilder str = new StringBuilder("{" + " com.wurmonline.server.Message mess;"); for (String anInfoTabLine : infoTabLine) { @@ -341,12 +373,11 @@ public static void preInit(){ Util.instrumentDeclared(thisClass, ctMethodsItems, "improveItem", "isCombine", replace); // - Check new improve materials - // - // TODO: Re-enable when custom items are created that require it. - /*replace = "int temp = "+ItemMod.class.getName()+".getModdedImproveTemplateId($1);" + replace = "int temp = "+ItemMod.class.getName()+".getModdedImproveTemplateId($1);" + "if(temp != -10){" + " return temp;" + "}"; - Util.insertBeforeDeclared(thisClass, ctMethodsItems, "getImproveTemplateId", replace);*/ + Util.insertBeforeDeclared(thisClass, ctMethodsItems, "getImproveTemplateId", replace); // - Remove fatiguing actions requiring you to be on the ground - // CtClass ctAction = classPool.get("com.wurmonline.server.behaviours.Action"); @@ -401,8 +432,16 @@ public void edit(MethodCall m) throws CannotCompileException { 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);"); + replace = MiscChanges.class.getName()+".broadCastDeaths($1, $2);"; + Util.insertBeforeDeclared(thisClass, ctPlayers, "broadCastDeathInfo", replace); + + Util.setReason("Broadcast player death tabs always."); + replace = MiscChanges.class.getName()+".broadCastDeathsPvE($0, $0.attackers);"; + Util.insertBeforeDeclared(thisClass, ctPlayer, "modifyRanking", replace); + + Util.setReason("Disable PvP only death tabs."); + replace = "$_ = true;"; + Util.instrumentDeclared(thisClass, ctPlayers, "broadCastDeathInfo", "isThisAPvpServer", replace); Util.setReason("Attempt to prevent libila from losing faith when crossing servers."); CtClass ctIntraServerConnection = classPool.get("com.wurmonline.server.intra.IntraServerConnection"); @@ -692,7 +731,6 @@ public void edit(MethodCall m) throws CannotCompileException { // How to add a skill! /*CtClass ctSkillSystem = classPool.get("com.wurmonline.server.skills.SkillSystem"); CtConstructor ctSkillSystemConstructor = ctSkillSystem.getClassInitializer(); - logathing("Test first"); ctSkillSystemConstructor.insertAfter("com.wurmonline.server.skills.SkillSystem.addSkillTemplate(new "+SkillTemplate.class.getName()+"(10096, \"Battle Yoyos\", 4000.0f, new int[]{1022}, 1209600000l, (short) 4, true, true));");*/ @@ -741,51 +779,12 @@ public void edit(MethodCall m) throws CannotCompileException { replace = "$_ = 1;"; Util.instrumentDeclared(thisClass, ctAbilities, "isInProperLocation", "getTemplateId", replace); - /*Util.setReason("Debug Login Handler when creating a new player via an exception."); - CtClass ctLoginHandler = classPool.get("com.wurmonline.server.LoginHandler"); - replace = "$_ = $proceed($$);" + - "logger.info(ex.getMessage());"; - Util.instrumentDeclared(thisClass, ctLoginHandler, "handleLogin", "doNewPlayer", replace); - replace = "$_ = $proceed($$);" + - "logger.info(\"addPlayer(\"+$1+\")\");"; - Util.instrumentDeclared(thisClass, ctLoginHandler, "handleLogin", "addPlayer", replace); - replace = "$_ = $proceed($$);" + - "logger.info(\"initialisePlayer(\"+$1+\")\");"; - Util.instrumentDeclared(thisClass, ctLoginHandler, "handleLogin", "initialisePlayer", replace); - replace = "$_ = $proceed($$);" + - "logger.info(\"createBodyParts\");"; - Util.instrumentDeclared(thisClass, ctLoginHandler, "handleLogin", "createBodyParts", replace); - replace = "logger.info(\"loadSkills\");" + - "$_ = $proceed($$);"; - Util.instrumentDeclared(thisClass, ctLoginHandler, "handleLogin", "loadSkills", replace); - replace = "logger.info(\"loadAllItemsForCreature1(\"+$1+\")\");" + - "logger.info(\"loadAllItemsForCreature2(\"+$1.getStatus()+\")\");" + - "logger.info(\"loadAllItemsForCreature3(\"+$2+\")\");" + - "try{" + - " $_ = $proceed($$);" + - "}catch(com.wurmonline.server.NoSuchItemException ex){" + - " logger.info(ex.getMessage());" + + Util.setReason("Make the key of the heavens only usable on PvE"); + replace = "if($1.getTemplateId() == 794 && com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " $2.getCommunicator().sendNormalServerMessage(\"The \"+$1.getName()+\" may not be used on Arena.\");" + + " return false;" + "}"; - Util.instrumentDeclared(thisClass, ctLoginHandler, "handleLogin", "loadAllItemsForCreature", replace); - - // -- Items method debugging -- // - Util.setReason("Debug Items method loadAllitemsForCreature"); - CtClass ctItems = classPool.get("com.wurmonline.server.Items"); - replace = "logger.info(\"creature = \"+$1+\", inventoryId = \"+$2);"; - Util.insertBeforeDeclared(thisClass, ctItems, "loadAllItemsForCreature", replace); - replace = "logger.info(\"loadPossessions(\"+$1+\")\");" + - "$_ = $proceed($$);"; - Util.instrumentDeclared(thisClass, ctItems, "loadAllItemsForCreature", "loadPossessions", replace); - - replace = "logger.info(\"sendMapInfo - Communicator: \"+$0);" + - "$_ = $proceed($$);"; - Util.instrumentDeclared(thisClass, ctLoginHandler, "handleLogin", "sendMapInfo", replace); - replace = "logger.info(\"loadAllPrivatePOIForPlayer(\"+$1+\")\");" + - "$_ = $proceed($$);"; - Util.instrumentDeclared(thisClass, ctLoginHandler, "handleLogin", "loadAllPrivatePOIForPlayer", replace); - replace = "$_ = $proceed($$);" + - "logger.info(\"resetLastSentToolbelt\");"; - Util.instrumentDeclared(thisClass, ctLoginHandler, "handleLogin", "resetLastSentToolbelt", replace);*/ + Util.insertBeforeDeclared(thisClass, ctAbilities, "isInProperLocation", replace); Util.setReason("Make drinks less filling."); CtClass[] params13 = { @@ -795,11 +794,67 @@ public void edit(MethodCall m) throws CannotCompileException { CtClass.floatType }; String desc13 = Descriptor.ofMethod(CtClass.booleanType, params13); - replace = "$_ = $proceed($1, $2, $3*5);"; + replace = "if(template != 128){" + + " $_ = $proceed($1, $2, $3*5);" + + "}else{" + + " $_ = $proceed($$);" + + "}"; Util.instrumentDescribed(thisClass, ctMethodsItems, "drink", desc13, "sendActionControl", replace); - replace = "$_ = $proceed($1/5, $2, $3, $4, $5);"; + replace = "if(template != 128){" + + " $_ = $proceed($1/5, $2, $3, $4, $5);" + + "}else{" + + " $_ = $proceed($$);" + + "}"; Util.instrumentDescribed(thisClass, ctMethodsItems, "drink", desc13, "modifyThirst", replace); + Util.setReason("Disable Gem Augmentation skill from converting."); + CtClass ctMethodsReligion = classPool.get("com.wurmonline.server.behaviours.MethodsReligion"); + replace = "$_ = $proceed($1, $2, true, $4);"; + Util.instrumentDeclared(thisClass, ctMethodsReligion, "listen", "skillCheck", replace); + + Util.setReason("Disable GM commands from displaying in /help unless the player is a GM."); + CtClass ctServerTweaksHandler = classPool.get("com.wurmonline.server.ServerTweaksHandler"); + replace = "if($1.getPower() < 1){" + + " return;" + + "}"; + Util.insertBeforeDeclared(thisClass, ctServerTweaksHandler, "sendHelp", replace); + + Util.setReason("Make damage less likely to interrupt actions during combat."); + replace = "$1 = $1/2;"; + Util.insertBeforeDeclared(thisClass, ctCreature, "maybeInterruptAction", replace); + + Util.setReason("Fix mission null pointer exception."); + CtClass ctEpicServerStatus = classPool.get("com.wurmonline.server.epic.EpicServerStatus"); + replace = "if(itemplates.size() < 1){" + + " com.wurmonline.server.epic.EpicServerStatus.setupMissionItemTemplates();" + + "}"; + Util.insertBeforeDeclared(thisClass, ctEpicServerStatus, "getRandomItemTemplateUsed", replace); + + Util.setReason("Fix bug causing high cast spells to reduce power."); + CtClass ctSpellEffect = classPool.get("com.wurmonline.server.spells.SpellEffect"); + replace = "{" + + " final float mod = 5.0f * (1.0f - java.lang.Math.min($0.getPower(), 100f) / 100.0f);" + + " $0.setPower(mod + $1);" + + "}"; + Util.setBodyDeclared(thisClass, ctSpellEffect, "improvePower", replace); + + Util.setReason("Disable smelting pots from being used."); + CtClass ctItemBehaviour = classPool.get("com.wurmonline.server.behaviours.ItemBehaviour"); + CtClass[] params14 = { + ctAction, + ctCreature, + ctItem, + ctItem, + CtClass.shortType, + CtClass.floatType + }; + String desc14 = Descriptor.ofMethod(CtClass.booleanType, params14); + replace = "if($5 == 519){" + + " $2.getCommunicator().sendNormalServerMessage(\"Smelting is disabled.\");" + + " return true;" + + "}"; + Util.insertBeforeDescribed(thisClass, ctItemBehaviour, "action", desc14, replace); + } catch (CannotCompileException | NotFoundException | IllegalArgumentException | ClassCastException e) { throw new HookException(e); } diff --git a/src/main/java/mod/sin/wyvern/PlayerTitles.java b/src/main/java/mod/sin/wyvern/PlayerTitles.java index 10a41c6..8c4d056 100644 --- a/src/main/java/mod/sin/wyvern/PlayerTitles.java +++ b/src/main/java/mod/sin/wyvern/PlayerTitles.java @@ -80,6 +80,9 @@ public static void preInit(){ customTitles.put("Piratemax", 810); // Slave playerTitles.put("Piratemax", "Boy Next Door"); + donatorTitles.add("Eltacolad"); + customTitles.put("Eltacolad", 811); // The One True Taco + // Other rewards customTitles.put("Critias", 602); } diff --git a/src/main/java/mod/sin/wyvern/SkillChanges.java b/src/main/java/mod/sin/wyvern/SkillChanges.java index 73cae28..ea286b1 100644 --- a/src/main/java/mod/sin/wyvern/SkillChanges.java +++ b/src/main/java/mod/sin/wyvern/SkillChanges.java @@ -37,16 +37,19 @@ public static double newDoSkillGainNew(Skill skill, double check, double power, try { Skills parent = ReflectionUtil.getPrivateField(skill, ReflectionUtil.getField(skill.getClass(), "parent")); double advanceMultiplicator = (100.0 - skill.getKnowledge()) / (skill.getDifficulty(parent.priest) * skill.getKnowledge() * skill.getKnowledge()) * learnMod * bonus; - double p = 5; - double q = 3; + double negativeDecayRate = 5; + double positiveDecayRate = 3; + double valueAtZero = 3.74d; + double valueAtOneHundred = 0.9d; //advanceMultiplicator *= Math.pow(2, ((2-Math.pow((100/(100+power)), p))*(100-power)/100)); - double mult = Math.pow(2, (2-Math.pow(100/(100+power), p))*Math.pow((100-power)*0.01, q)); + //double mult = Math.pow(2, (2-Math.pow(100/(100+power), negativeDecayRate))*Math.pow((100-power)*0.01, positiveDecayRate)); + double mult = valueAtOneHundred*Math.pow(valueAtZero/valueAtOneHundred, (2-Math.pow(100/(100+Math.max(-99,power)), negativeDecayRate))*Math.pow((100-power)*0.01, positiveDecayRate)); if(mult < 0.5 && skill.getKnowledge() < 20){ advanceMultiplicator *= 0.5+(Server.rand.nextDouble()*0.5); }else if(skill.getNumber() == SkillList.MEDITATING || skill.getNumber() == SkillList.LOCKPICKING){ advanceMultiplicator *= Math.max(mult, 0.8d); }else if(mult > 0.0001) { - advanceMultiplicator *= mult*0.95d; + advanceMultiplicator *= mult; }else{ advanceMultiplicator = 0; } diff --git a/src/main/java/mod/sin/wyvern/Titans.java b/src/main/java/mod/sin/wyvern/Titans.java index 5c1edd2..94d80b9 100644 --- a/src/main/java/mod/sin/wyvern/Titans.java +++ b/src/main/java/mod/sin/wyvern/Titans.java @@ -153,7 +153,8 @@ public static void lilithMyceliumVoidAttack(Creature titan, Creature lCret, int if (lCret.isUnique() || lCret.isInvulnerable() || lCret == titan || isTitanMinion(lCret)){ return; } - if (!lCret.addWoundOfType(lCret, Wound.TYPE_INFECTION, 1, true, 1.0f, true, 50000f)) { + lCret.addWoundOfType(lCret, Wound.TYPE_INFECTION, 1, true, 1.0f, true, 50000f); + /*if (!lCret.addWoundOfType(lCret, Wound.TYPE_INFECTION, 1, true, 1.0f, true, 50000f)) { Creatures.getInstance().setCreatureDead(lCret); Players.getInstance().setCreatureDead(lCret); lCret.setTeleportPoints((short)tilex, (short)tiley, titan.getLayer(), 0); @@ -163,7 +164,7 @@ public static void lilithMyceliumVoidAttack(Creature titan, Creature lCret, int if (!lCret.isPlayer()) { lCret.getMovementScheme().resumeSpeedModifier(); } - } + }*/ } public static void ifritMassIncinerateAttack(Creature titan, Creature lCret){ if (lCret.isUnique() || lCret.isInvulnerable() || lCret == titan || isTitanMinion(lCret)){ @@ -681,7 +682,7 @@ public static void pollTitanRegeneration(){ for (Creature cret : titans) { if (cret.getBody().isWounded()) { Wounds tWounds = cret.getBody().getWounds(); - int toHeal = 2; + int toHeal = 5; Wound w = tWounds.getWounds()[Server.rand.nextInt(tWounds.getWounds().length)]; if (w.getSeverity() > toHeal) { w.modifySeverity(-toHeal); diff --git a/src/main/java/mod/sin/wyvern/WyvernMods.java b/src/main/java/mod/sin/wyvern/WyvernMods.java index 75062cd..2517b7f 100644 --- a/src/main/java/mod/sin/wyvern/WyvernMods.java +++ b/src/main/java/mod/sin/wyvern/WyvernMods.java @@ -5,38 +5,29 @@ import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.nio.file.Paths; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; import java.util.Properties; import java.util.logging.FileHandler; import java.util.logging.Level; import java.util.logging.Logger; import java.util.logging.SimpleFormatter; -import com.wurmonline.server.Items; +import com.wurmonline.server.Message; import com.wurmonline.server.creatures.Communicator; import com.wurmonline.server.creatures.Creature; -import com.wurmonline.server.creatures.CreatureTemplate; -import com.wurmonline.server.creatures.CreatureTemplateFactory; import com.wurmonline.server.items.*; +import com.wurmonline.server.kingdom.Kingdoms; import mod.sin.actions.items.SorcerySplitAction; import mod.sin.lib.Util; import org.gotti.wurmunlimited.modloader.ReflectionUtil; import org.gotti.wurmunlimited.modloader.classhooks.HookException; import org.gotti.wurmunlimited.modloader.classhooks.HookManager; import org.gotti.wurmunlimited.modloader.interfaces.*; -import org.gotti.wurmunlimited.modsupport.ModSupportDb; import org.gotti.wurmunlimited.modsupport.actions.ModActions; import org.gotti.wurmunlimited.modsupport.creatures.ModCreatures; import org.gotti.wurmunlimited.modsupport.vehicles.ModVehicleBehaviours; import com.wurmonline.server.TimeConstants; import com.wurmonline.server.players.Player; -import com.wurmonline.server.skills.SkillList; -import com.wurmonline.server.skills.SkillSystem; -import com.wurmonline.server.skills.SkillTemplate; import javassist.CannotCompileException; import javassist.ClassPool; @@ -51,7 +42,7 @@ import mod.sin.wyvern.mastercraft.Mastercraft; public class WyvernMods -implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCreatedListener, ServerStartedListener, ServerPollListener, PlayerLoginListener { +implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCreatedListener, ServerStartedListener, ServerPollListener, PlayerLoginListener, ChannelMessageListener { private static Logger logger = Logger.getLogger(WyvernMods.class.getName()); public static boolean espCounter = false; public static boolean enableDepots = false; @@ -155,6 +146,8 @@ public void preInit() { Mastercraft.preInit(); Mastercraft.addNewTitles(); SupplyDepots.preInit(); + KeyEvent.preInit(); + //GemAugmentation.preInit(); Class thisClass = WyvernMods.class; ClassPool classPool = HookManager.getInstance().getClassPool(); @@ -288,6 +281,7 @@ public void onServerStarted() { ModActions.registerAction(new LeaderboardAction()); ModActions.registerAction(new AddSubGroupAction()); ModActions.registerAction(new SorcerySplitAction()); + ModActions.registerAction(new LeaderboardSkillAction()); logger.info("Registering Arena actions."); ModActions.registerAction(new SorceryCombineAction()); //ModActions.registerAction(new VillageTeleportAction()); // [3/28/18] Disabled - Highway Portals added instead. @@ -410,4 +404,14 @@ public void onServerPoll() { } } + @Override + public MessagePolicy onKingdomMessage(Message message) { + String window = message.getWindow(); + if(window.startsWith("GL-Freedom") && KeyEvent.isActive()){ + KeyEvent.handlePlayerMessage(message); + } + + return MessagePolicy.PASS; + } + } \ No newline at end of file diff --git a/src/main/java/mod/sin/wyvern/bounty/LootBounty.java b/src/main/java/mod/sin/wyvern/bounty/LootBounty.java index a3cecbd..6afd463 100644 --- a/src/main/java/mod/sin/wyvern/bounty/LootBounty.java +++ b/src/main/java/mod/sin/wyvern/bounty/LootBounty.java @@ -9,6 +9,7 @@ import com.wurmonline.server.items.*; import com.wurmonline.server.villages.Village; import com.wurmonline.server.villages.Villages; +import mod.piddagoras.duskombat.DamageEngine; import mod.sin.creatures.Reaper; import mod.sin.creatures.SpectralDrake; import mod.sin.items.AffinityOrb; @@ -29,14 +30,14 @@ public class LootBounty { protected static final Random random = new Random(); public static void displayLootAssistance(Creature mob){ - if(Bounty.dealtDamage.containsKey(mob.getWurmId())){ + if(DamageEngine.dealtDamage.containsKey(mob.getWurmId())){ logger.info("Found the damageDealt entry, parsing..."); ArrayList names = new ArrayList(); ArrayList damages = new ArrayList(); - for(long creatureId : Bounty.dealtDamage.get(mob.getWurmId()).keySet()){ + for(long creatureId : DamageEngine.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)); + damages.add(DamageEngine.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."); @@ -145,7 +146,7 @@ public static void insertUniqueLoot(Creature mob, Item corpse){ } public static void blessWorldWithMoonVeins(Creature mob){ - int i = 10+Server.rand.nextInt(6); + int i = 8+Server.rand.nextInt(5); while(i > 0){ int x = random.nextInt(Server.surfaceMesh.getSize()); int y = random.nextInt(Server.surfaceMesh.getSize()); @@ -158,8 +159,8 @@ public static void blessWorldWithMoonVeins(Creature mob){ 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) { + for (int vx = -20; vx < 20; vx += 5) { + for (int vy = -20; vy < 20 && (v = Villages.getVillage(x + vx, y + vy, true)) == null; vy += 5) { } if(v != null){ break; @@ -168,6 +169,7 @@ public static void blessWorldWithMoonVeins(Creature mob){ } if(v != null){ HistoryManager.addHistory(mob.getTemplate().getName(), "blesses the world with a "+tileType.getName()+" near "+v.getName()+"!"); + MiscChanges.sendServerTabMessage("rumors",mob.getTemplate().getName()+" blesses the world with a "+tileType.getName()+" near "+v.getName()+"!", 255, 255, 255); } logger.info("Placed a "+tileType.getName()+" at "+x+", "+y+" - "+height+" height"); i--; diff --git a/src/main/java/mod/sin/wyvern/bounty/PlayerBounty.java b/src/main/java/mod/sin/wyvern/bounty/PlayerBounty.java index 18ffe04..5a97db2 100644 --- a/src/main/java/mod/sin/wyvern/bounty/PlayerBounty.java +++ b/src/main/java/mod/sin/wyvern/bounty/PlayerBounty.java @@ -20,6 +20,7 @@ import com.wurmonline.server.players.Titles.Title; import com.wurmonline.server.skills.NoSuchSkillException; import com.wurmonline.server.skills.SkillList; +import mod.piddagoras.duskombat.DamageEngine; import mod.sin.armour.SpectralHide; import mod.sin.creatures.Reaper; import mod.sin.creatures.SpectralDrake; @@ -128,7 +129,7 @@ public static void checkPlayerReward(Player player, Creature mob){ return; } } - if(Bounty.dealtDamage.containsKey(mobWurmId) && Bounty.dealtDamage.get(mobWurmId).containsKey(player.getWurmId())){ + if(DamageEngine.dealtDamage.containsKey(mobWurmId) && DamageEngine.dealtDamage.get(mobWurmId).containsKey(player.getWurmId())){ // -- Damage Dealt Rewards -- // /*if(mob.isUnique()){ // Treasure boxes awarded to players who deal damage: diff --git a/src/main/java/mod/sin/wyvern/mastercraft/Mastercraft.java b/src/main/java/mod/sin/wyvern/mastercraft/Mastercraft.java index f0a5b18..af11de8 100644 --- a/src/main/java/mod/sin/wyvern/mastercraft/Mastercraft.java +++ b/src/main/java/mod/sin/wyvern/mastercraft/Mastercraft.java @@ -112,6 +112,7 @@ public static void addNewTitles(){ ExtendTitleEnum.getSingletonInstance().addExtendEntry("Genocide_GrandDesigner", 808, "Grand Designer", "Grand Designer", -1, "NORMAL"); ExtendTitleEnum.getSingletonInstance().addExtendEntry("Seleas_CrazyCatLord", 809, "The Crazy Cat Lord", "The Crazy Cat Lord", -1, "NORMAL"); ExtendTitleEnum.getSingletonInstance().addExtendEntry("Piratemax_Slave", 810, "Slave", "Slave", -1, "NORMAL"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Eltacolad_TrueTaco", 811, "The One True Taco", "The One True Taco", -1, "NORMAL"); // Characteristic Titles ExtendTitleEnum.getSingletonInstance().addExtendEntry("MindLogic_Normal", 1000, "Logical", "Logical", 100, "NORMAL");