diff --git a/Changelog.txt b/Changelog.txt index a01c4407d..57bb14c62 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -19,6 +19,7 @@ Version 1.4.00-dev + Added timeout on party teleport requests + Added XP bonus for Archery based on distance from shooter to target + Added ability to config Hylian Luck drops through treasures.yml + + Added party XP sharing = Fixed Spout not being able to precache our resources properly, and therefore making our XP bars fail = Fixed Spout config files loading / generating when they shouldn't have = Fixed mod config files loading / generating when they shouldn't have diff --git a/src/main/java/com/gmail/nossr50/config/Config.java b/src/main/java/com/gmail/nossr50/config/Config.java index 517b0343c..483904d32 100644 --- a/src/main/java/com/gmail/nossr50/config/Config.java +++ b/src/main/java/com/gmail/nossr50/config/Config.java @@ -288,7 +288,7 @@ public class Config extends ConfigLoader { public boolean getHerbalismAFKDisabled() { return config.getBoolean("Skills.Herbalism.Prevent_AFK_Leveling", true); } /* Dogde Lightning */ - public boolean getDodgeLightningDisabled() {return config.getBoolean("Skills.Acrobatics.Prevent_Dodge_Lightning", false); } + public boolean getDodgeLightningDisabled() { return config.getBoolean("Skills.Acrobatics.Prevent_Dodge_Lightning", false); } /* Level Caps */ public int getLevelCapAcrobatics() { @@ -428,4 +428,10 @@ public class Config extends ConfigLoader { int cap = config.getInt(configString, 0); return ((cap <= 0) ? Integer.MAX_VALUE : cap); } + + /* Party Settings */ + public boolean getExpShareEnabled() { return config.getBoolean("Party.Sharing.ExpShare_enabled", true); } + public double getPartyShareBonus() { return config.getDouble("Party.Sharing.ExpShare_bonus", 1.1); } + public boolean getItemShareEnabled() { return config.getBoolean("Party.Sharing.ItemShare_enabled", true); } + public double getPartyShareRange() { return config.getDouble("Party.Sharing.Range", 75.0); } } diff --git a/src/main/java/com/gmail/nossr50/datatypes/McMMOPlayer.java b/src/main/java/com/gmail/nossr50/datatypes/McMMOPlayer.java index 069aa0b4f..750b7efb1 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/McMMOPlayer.java +++ b/src/main/java/com/gmail/nossr50/datatypes/McMMOPlayer.java @@ -12,10 +12,8 @@ import com.gmail.nossr50.party.Party; import com.gmail.nossr50.party.PartyManager; import com.gmail.nossr50.skills.SkillType; import com.gmail.nossr50.spout.huds.SpoutHud; -import com.gmail.nossr50.util.Misc; import com.gmail.nossr50.util.ModChecks; import com.gmail.nossr50.util.Permissions; -import com.gmail.nossr50.util.Users; public class McMMOPlayer { private Player player; @@ -49,33 +47,6 @@ public class McMMOPlayer { return powerLevel; } - /** - * Calculate the party XP modifier. - * - * @param skillType Type of skill to check - * @return the party bonus multiplier - */ - private double calculatePartyXPModifier(SkillType skillType) { - double bonusModifier = 0.0; - - for (Player member : party.getOnlineMembers()) { - if (party.getLeader().equals(member.getName())) { - if (Misc.isNear(player.getLocation(), member.getLocation(), 25.0)) { - PlayerProfile partyLeader = Users.getProfile(member); - int leaderSkill = partyLeader.getSkillLevel(skillType); - int playerSkill = profile.getSkillLevel(skillType); - - if (leaderSkill >= playerSkill) { - int difference = leaderSkill - playerSkill; - bonusModifier = (difference * 0.75) / 100.0; - } - } - } - } - - return bonusModifier; - } - /** * Adds XP to the player, doesn't calculate for XP Rate * @@ -132,23 +103,8 @@ public class McMMOPlayer { return; } - double bonusModifier = 0; - - if (inParty()) { - bonusModifier = calculatePartyXPModifier(skillType); - } - int xp = (int)Math.floor((newValue / skillType.getXpModifier()) * Config.getInstance().getExperienceGainsGlobalMultiplier()); - if (bonusModifier > 0) { - if (bonusModifier >= 2) { - bonusModifier = 2; - } - - double trueBonus = bonusModifier * xp; - xp += trueBonus; - } - if (Config.getInstance().getToolModsEnabled()) { ItemStack item = player.getItemInHand(); CustomTool tool = ModChecks.getToolFromItemStack(item); diff --git a/src/main/java/com/gmail/nossr50/party/Party.java b/src/main/java/com/gmail/nossr50/party/Party.java index d622b153d..adf629e31 100644 --- a/src/main/java/com/gmail/nossr50/party/Party.java +++ b/src/main/java/com/gmail/nossr50/party/Party.java @@ -13,6 +13,7 @@ public class Party { private String name; private String password; private boolean locked; + private String expShareMode; public List getMembers() { return members; @@ -62,4 +63,12 @@ public class Party { public void setLocked(boolean locked) { this.locked = locked; } + + public void setExpShareMode(String expShareMode) { + this.expShareMode = expShareMode; + } + + public String getExpShareMode() { + return expShareMode; + } } diff --git a/src/main/java/com/gmail/nossr50/party/PartyManager.java b/src/main/java/com/gmail/nossr50/party/PartyManager.java index efa866506..47e634252 100644 --- a/src/main/java/com/gmail/nossr50/party/PartyManager.java +++ b/src/main/java/com/gmail/nossr50/party/PartyManager.java @@ -10,6 +10,7 @@ import org.bukkit.entity.Player; import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.datatypes.PlayerProfile; import com.gmail.nossr50.locale.LocaleLoader; +import com.gmail.nossr50.util.Misc; import com.gmail.nossr50.util.Users; public final class PartyManager { @@ -43,6 +44,25 @@ public final class PartyManager { return true; } + /** + * Get the near party members. + * + * @param player The player to check + * @param range The distance + * @return the near party members + */ + public static List getNearMembers(Player player, Party party, double range) { + List nearMembers = new ArrayList(); + if (party != null) { + for (Player member : party.getOnlineMembers()) { + if (player != member && Misc.isNear(player.getLocation(), member.getLocation(), range)) { + nearMembers.add(member); + } + } + } + return nearMembers; + } + /** * Notify party members when a player joins * @@ -224,6 +244,7 @@ public final class PartyManager { party.setName(partyName); party.setLeader(playerName); + party.setExpShareMode("NO_SHARE"); party.setLocked(true);//Parties are now invite-only by default, can be set to open with /party unlock if (password != null) { @@ -439,6 +460,7 @@ public final class PartyManager { party.setLeader(partiesFile.getString(partyName + ".Leader")); party.setPassword(partiesFile.getString(partyName + ".Password")); party.setLocked(partiesFile.getBoolean(partyName + ".Locked")); + party.setExpShareMode(partiesFile.getString(partyName + ".ExpShareMode")); party.getMembers().addAll(partiesFile.getStringList(partyName + ".Members")); parties.add(party); @@ -463,6 +485,7 @@ public final class PartyManager { partiesFile.set(partyName + ".Leader", party.getLeader()); partiesFile.set(partyName + ".Password", party.getPassword()); partiesFile.set(partyName + ".Locked", party.isLocked()); + partiesFile.set(partyName + ".ExpShareMode", party.getExpShareMode()); partiesFile.set(partyName + ".Members", party.getMembers()); try { diff --git a/src/main/java/com/gmail/nossr50/party/ShareHandler.java b/src/main/java/com/gmail/nossr50/party/ShareHandler.java new file mode 100644 index 000000000..03ef27a93 --- /dev/null +++ b/src/main/java/com/gmail/nossr50/party/ShareHandler.java @@ -0,0 +1,72 @@ +package com.gmail.nossr50.party; + +import java.util.List; + +import org.bukkit.entity.Player; + +import com.gmail.nossr50.config.Config; +import com.gmail.nossr50.skills.SkillTools; +import com.gmail.nossr50.skills.SkillType; +import com.gmail.nossr50.util.Users; + +public class ShareHandler { + + public static boolean expShareEnabled = Config.getInstance().getExpShareEnabled(); + public static boolean itemShareEnabled = Config.getInstance().getItemShareEnabled(); + public static double partyShareRange = Config.getInstance().getPartyShareRange(); + public static double partyShareBonus = Config.getInstance().getPartyShareBonus(); + + protected enum PartyShareType { + NO_SHARE, + RANDOM, + EQUAL, + }; + + public static double checkXpSharing(int oldExp, Player player, Party party, SkillType type) { + int newExp = oldExp; + if (party.getExpShareMode() == null) { + party.setExpShareMode("NO_SHARE"); + } + if (party.getExpShareMode().equals("NO_SHARE")) { + return newExp; + } else if (party.getExpShareMode().equals("EQUAL")) { + newExp = (int) calculateSharedExp(oldExp, player, party, type); + } + return newExp; + } + + /** + * Calculate the party XP. + * + * @param int XP without party sharing + * @return the party shared XP + */ + public static double calculateSharedExp(int oldExp, Player player, Party party, SkillType type) { + int newExp = oldExp; + List nearMembers = PartyManager.getNearMembers(player, party, partyShareRange); + + if (nearMembers.size() > 0) { + newExp = (int) ((oldExp / (nearMembers.size() + 1)) * partyShareBonus); + } + return newExp; + } + + + /** + * Distribute XP amongst party members. + * + * @param int XP without party sharing + * @return the party share experience + */ + public static void handleEqualExpShare(int xp, Player player, Party party, SkillType skillType) { + List nearMembers = PartyManager.getNearMembers(player, party, partyShareRange); + + for (Player member : nearMembers) { + if (nearMembers.size() > 0) { + Users.getPlayer(member).addXP(skillType, xp); + + SkillTools.xpCheckSkill(skillType, member, Users.getProfile(member)); + } + } + } +} \ No newline at end of file diff --git a/src/main/java/com/gmail/nossr50/party/commands/PartyCommand.java b/src/main/java/com/gmail/nossr50/party/commands/PartyCommand.java index d4b4720a9..aa01c1c63 100644 --- a/src/main/java/com/gmail/nossr50/party/commands/PartyCommand.java +++ b/src/main/java/com/gmail/nossr50/party/commands/PartyCommand.java @@ -15,6 +15,7 @@ import com.gmail.nossr50.events.party.McMMOPartyChangeEvent.EventReason; import com.gmail.nossr50.locale.LocaleLoader; import com.gmail.nossr50.party.Party; import com.gmail.nossr50.party.PartyManager; +import com.gmail.nossr50.party.ShareHandler; import com.gmail.nossr50.util.Users; public class PartyCommand implements CommandExecutor { @@ -56,7 +57,7 @@ public class PartyCommand implements CommandExecutor { return quit(); } else if (args[0].equalsIgnoreCase("expshare")) { - return shareExp(); + return shareExp(args); } else if (args[0].equalsIgnoreCase("itemshare")) { return shareItem(); @@ -109,6 +110,14 @@ public class PartyCommand implements CommandExecutor { String leader = party.getLeader(); StringBuffer tempList = new StringBuffer(); + int membersNear = PartyManager.getNearMembers(player, party, ShareHandler.partyShareRange).size(); + int membersOnline = party.getOnlineMembers().size() - 1; + + String ItemShare = ""; + String ExpShare = ""; + String Split = ""; + String itemShareMode = "NONE"; + for (String otherPlayerName : party.getMembers()) { if (leader.equals(otherPlayerName)) { tempList.append(ChatColor.GOLD); @@ -123,13 +132,28 @@ public class PartyCommand implements CommandExecutor { } String status = LocaleLoader.getString("Party.Status.Locked"); - if (!party.isLocked()) + if (!party.isLocked()) { status = LocaleLoader.getString("Party.Status.Unlocked"); + } player.sendMessage(LocaleLoader.getString("Commands.Party.Header")); player.sendMessage(LocaleLoader.getString("Commands.Party.Status", new Object[] {party.getName(), status})); -// player.sendMessage(LocaleLoader.getString("Commands.Party.ShareMode", new Object[] { "NONE", "NONE" })); Party share modes will get implemented later + + if (ShareHandler.expShareEnabled) { + ExpShare = LocaleLoader.getString("Commands.Party.ExpShare", new Object[] { party.getExpShareMode() }); + } + if (ShareHandler.itemShareEnabled) { + ItemShare = LocaleLoader.getString("Commands.Party.ItemShare", new Object[] { itemShareMode }); + } + if (ShareHandler.expShareEnabled && ShareHandler.itemShareEnabled) { + Split = ChatColor.DARK_GRAY + " || "; + } + if (ShareHandler.expShareEnabled || ShareHandler.itemShareEnabled) { + player.sendMessage(LocaleLoader.getString("Commands.Party.ShareMode") + ExpShare + Split + ItemShare); + } + player.sendMessage(LocaleLoader.getString("Commands.Party.Members.Header")); + player.sendMessage(LocaleLoader.getString("Commands.Party.MembersNear", new Object[] { membersNear, membersOnline })); player.sendMessage(LocaleLoader.getString("Commands.Party.Members", new Object[] {tempList})); } else { @@ -325,8 +349,32 @@ public class PartyCommand implements CommandExecutor { return false; } - private boolean shareExp() { - return (!CommandHelper.noCommandPermissions(player, "mcmmo.commands.party.expshare")); + private boolean shareExp(String[] args) { + if (CommandHelper.noCommandPermissions(player, "mcmmo.commands.party.expshare")) + return true; + String playerName = player.getName(); + PlayerProfile playerProfile = Users.getProfile(player); + Party party = playerProfile.getParty(); + + if (args.length < 2) { + player.sendMessage(LocaleLoader.getString("Commands.Usage.2", new Object[] {"party", "expshare", "[sharemode]"})); + return true; + } + + if (party.getLeader().equals(playerName)) { + if(args[1].equalsIgnoreCase("noshare") || args[1].equalsIgnoreCase("none") || args[1].equalsIgnoreCase("false")) { + party.setExpShareMode("NONE"); + for (Player onlineMembers : party.getOnlineMembers()) { + onlineMembers.sendMessage(LocaleLoader.getString("Commands.Party.SetSharing", new Object[] {LocaleLoader.getString("Party.ShareType.Exp"), LocaleLoader.getString("Party.ShareMode.NoShare")})); + } + } else if(args[1].equalsIgnoreCase("equal") || args[1].equalsIgnoreCase("even")) { + party.setExpShareMode("EQUAL"); + for (Player onlineMembers : party.getOnlineMembers()) { + onlineMembers.sendMessage(LocaleLoader.getString("Commands.Party.SetSharing", new Object[] {LocaleLoader.getString("Party.ShareType.Exp"), LocaleLoader.getString("Party.ShareMode.Equal")})); + } + } + } + return true; } private boolean shareItem() { diff --git a/src/main/java/com/gmail/nossr50/party/commands/PtpCommand.java b/src/main/java/com/gmail/nossr50/party/commands/PtpCommand.java index a671ea3f0..933f60800 100644 --- a/src/main/java/com/gmail/nossr50/party/commands/PtpCommand.java +++ b/src/main/java/com/gmail/nossr50/party/commands/PtpCommand.java @@ -26,7 +26,7 @@ public class PtpCommand implements CommandExecutor { @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - String usage = LocaleLoader.getString("Commands.Usage.1", new Object[] {"ptp", "<" + LocaleLoader.getString("Commands.Usage.Player") + ">"}); + String usage = LocaleLoader.getString("Commands.Usage.1", new Object[] { "ptp", "<" + LocaleLoader.getString("Commands.Usage.Player") + ">" }); if (CommandHelper.noConsoleUsage(sender)) { return true; diff --git a/src/main/java/com/gmail/nossr50/skills/SkillTools.java b/src/main/java/com/gmail/nossr50/skills/SkillTools.java index 3c7648ee2..2c8fb0dfc 100644 --- a/src/main/java/com/gmail/nossr50/skills/SkillTools.java +++ b/src/main/java/com/gmail/nossr50/skills/SkillTools.java @@ -14,6 +14,7 @@ import com.gmail.nossr50.config.Config; import com.gmail.nossr50.datatypes.PlayerProfile; import com.gmail.nossr50.events.experience.McMMOPlayerLevelUpEvent; import com.gmail.nossr50.locale.LocaleLoader; +import com.gmail.nossr50.party.ShareHandler; import com.gmail.nossr50.spout.SpoutConfig; import com.gmail.nossr50.spout.SpoutTools; import com.gmail.nossr50.util.Misc; @@ -523,6 +524,11 @@ public class SkillTools { return; } + if (profile.inParty()) { + xp = (int) ShareHandler.checkXpSharing(xp, player, profile.getParty(), type); + ShareHandler.handleEqualExpShare(xp, player, profile.getParty(), type); + } + Users.getPlayer(player).addXP(type, xp); xpCheckSkill(type, player, profile); } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index f582ef173..669a03cb3 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -65,6 +65,16 @@ Items: Feather_Cost: 10 Item_ID: 288 +# +# Settings for Parties +### +Party: + Sharing: + ExpShare_enabled: true + ExpShare_bonus: 1.1 + ItemShare_enabled: true + Range: 75.0 + # # Settings for Abilities ### diff --git a/src/main/resources/locale/locale_en_US.properties b/src/main/resources/locale/locale_en_US.properties index a28372032..50570e03c 100644 --- a/src/main/resources/locale/locale_en_US.properties +++ b/src/main/resources/locale/locale_en_US.properties @@ -439,7 +439,10 @@ Commands.NoConsole=This command does not support console usage. Commands.Other=[[GREEN]]--OTHER COMMANDS-- Commands.Party.Header=[[RED]]-----[][[GREEN]]PARTY[[RED]][]----- Commands.Party.Status=[[DARK_GRAY]]NAME: [[WHITE]]{0} {1} -Commands.Party.ShareMode=[[DARK_GRAY]]SHARE MODE: [[GRAY]]ITEM [[DARK_AQUA]]({0}) [[DARK_GRAY]]|| [[GRAY]]EXP [[DARK_AQUA]]({1}) +Commands.Party.ShareMode=[[DARK_GRAY]]SHARE MODE: +Commands.Party.ItemShare=[[GRAY]]ITEM [[DARK_AQUA]]({0}) +Commands.Party.ExpShare=[[GRAY]]EXP [[DARK_AQUA]]({0}) +Commands.Party.MembersNear=[[DARK_GRAY]]NEAR YOU [[DARK_AQUA]]{0}[[DARK_GRAY]]/[[DARK_AQUA]]{1} Commands.Party.Accept=[[RED]]- Accept party invite Commands.Party.Chat.Off=Party Chat only [[RED]]Off Commands.Party.Chat.On=Party Chat only [[GREEN]]On @@ -451,6 +454,7 @@ Commands.Party.Invite=[[RED]]- Send party invite Commands.Party.Join=[[GRAY]]Joined Party: {0} Commands.Party.Create=[[GRAY]]Created Party: {0} Commands.Party.Rename=[[GRAY]]Party name changed to: [[WHITE]]{0} +Commands.Party.SetSharing=[[GRAY]]Party {0} sharing set to: [[DARK_AQUA]]{1} Commands.Party.AlreadyExists=[[DARK_RED]]Party {0} already exists! Commands.Party.Kick=[[RED]]You were kicked from party {0}! Commands.Party.Leave=[[RED]]You have left that party @@ -539,6 +543,11 @@ Party.Unlocked=[[GRAY]]Party is unlocked Party.Disband=[[GRAY]]The party has been disbanded Party.Status.Locked=[[DARK_RED]](INVITE-ONLY) Party.Status.Unlocked=[[DARK_GREEN]](OPEN) +Party.ShareType.Exp=EXP +Party.ShareType.Item=ITEM +Party.ShareMode.NoShare=NONE +Party.ShareMode.Equal=EQUAL +Party.ShareMode.Random=RANDOM ##xp Commands.XPGain.Acrobatics=Falling